5 A Linux/Unix toolset and driver for Nokia mobile phones.
7 Released under the terms of the GNU GPL, see file COPYING for more details.
9 Mainline code for mgnetd daemon.
11 Last modification: 07.02.2002
12 Ralf Thelen <ralf@mythelen.de>
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <sys/errno.h>
26 #include <netinet/in.h>
29 #if defined(__svr4__) || defined(__FreeBSD__)
30 # include <strings.h> /* for bzero */
36 #include <sys/types.h>
41 #include "files/cfgreader.h"
42 #include "gsm-common.h"
50 /* Global variables */
51 char *Model; /* Model from .gnokiirc file. */
52 char *Port; /* Port from .gnokiirc file */
53 char *Initlength; /* Init length from .gnokiirc file */
54 char *Connection; /* Connection type from .gnokiirc file */
55 char *SynchronizeTime;
56 char *BinDir; /* Directory of the mgnokiidev command */
62 fprintf(stdout, _("mgnetd Version %d.%d, a udp server for mygnokii\n based on Version %s\n"
63 "Built %s %s for %s on %s \n")
64 ,MG_NET_API_MAJOR_VERSION,MG_NET_API_MINOR_VERSION, VERSION, __TIME__, __DATE__, Model, Port);
65 fprintf(stdout, _(" usage: mgnetd passwd\n"));
69 /* fbusinit is the generic function which waits for the FBUS link. The limit
70 is 10 seconds. After 10 seconds we quit. */
72 void fbusinit(void (*rlp_handler)(RLP_F96Frame *frame))
79 if (strcmp(GetMygnokiiVersion(),VERSION)!=0)
80 fprintf(stderr,_("WARNING: version of installed libmygnokii.so (%s) is different to version of mgnetd (%s)\n"),GetMygnokiiVersion(),VERSION);
83 /* Initialise the code for the GSM interface. */
84 error = GSM_Initialise(Model, Port, Initlength, GetConnectionTypeFromString(Connection), rlp_handler, SynchronizeTime);
86 if (error != GE_NONE) {
87 fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
91 /* First (and important!) wait for GSM link to be active. We allow 10
93 while (count++ < 200 && *GSM_LinkOK == false)
96 if (*GSM_LinkOK == false) {
97 fprintf (stderr, _("Hmmm... GSM_LinkOK never went true. Quitting.\n"));
105 simple udp-based server
107 int main(int argc, char *argv[])
111 MG_rq_version version;
112 MG_rq_identify ident;
113 MG_rq_memorystatus status;
114 MG_rq_phonebook_location ph;
117 GSM_PhonebookEntry entry;
118 GSM_MemoryStatus stats;
119 GSM_RFUnits rf_units = GRF_Arbitrary;
120 GSM_BatteryUnits batt_units = GBU_Arbitrary;
122 GSM_MultiSMSMessage MultiSMS;
123 GSM_SMSMessageType SMSType=GST_SMS;
125 bool SMSReply = false;
126 GSM_Coding_Type SMSCoding = GSM_Coding_Default;
127 GSM_UDH SMSUDHType = GSM_NoUDH;
131 char memory_type_string[20];
133 float rflevel=-1, batterylevel=-1;
135 time_t curr_t, last_t;
137 int s; /* socket descriptor */
138 int cc; /* contains the number of bytes read */
140 struct servent *sp; /* pointer to service information */
142 struct sockaddr_in myaddr; /* for local socket address */
143 struct sockaddr_in clientaddr; /* for client's socket address */
145 extern int errno; /* for unblocking io */
151 /* For GNU gettext */
153 textdomain("gnokii");
154 setlocale(LC_ALL, "pl_PL"); //here is string for Polish localisation
157 /* Read config file */
158 if (CFG_ReadConfig(&Model, &Port, &Initlength, &Connection, &BinDir, &SynchronizeTime,false) < 0) {
162 /* Handle command line arguments. */
163 if (argc != 2) usage();
165 /* get password from commandline */
166 strncpy(password,argv[1],8);
170 curr_t = last_t = time(NULL);
172 /* clear out address structures */
173 memset ((char *)&myaddr, 0, sizeof(struct sockaddr_in));
174 memset ((char *)&clientaddr, 0, sizeof(struct sockaddr_in));
176 /* Set up address structure for the socket. */
177 myaddr.sin_family = AF_INET;
178 myaddr.sin_addr.s_addr = INADDR_ANY;
180 sp = getservbyname ("mygnokii", "udp");
183 printf("mygnokii not found in /etc/services\n");
184 printf("using default port 50963\n");
186 myaddr.sin_port = htons(50963);
188 else myaddr.sin_port = sp->s_port;
191 /* Create the socket. */
192 s = socket (AF_INET, SOCK_DGRAM, 0);
195 printf("%s: unable to create socket\n", argv[0]);
199 /* Bind the server's address to the socket. */
200 if (bind(s, (struct sockaddr *) &myaddr, sizeof(struct sockaddr)) == -1) {
202 printf("%s: unable to bind address\n", argv[0]);
206 /* Make socket unblocking */
207 if ( fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
209 printf("%s: unable to make socket unblocking\n", argv[0]);
217 case -1: /* Unable to fork, for some reason. */
219 printf("%s: unable to fork daemon\n", argv[0]);
224 /* init GSM Interface */
226 printf("init done, daemonizing\n");
235 addrlen = sizeof(struct sockaddr_in);
237 cc = recvfrom(s, &rq, sizeof(rq), 0,
238 (struct sockaddr *) &clientaddr, &addrlen);
242 if ( errno != EAGAIN) exit(1);
244 { /* no data -> do some usefull things */
245 /* required for infrared connections to prevent timeouts */
247 if ( difftime(curr_t, last_t) > 5 )
249 if (GSM->GetRFLevel(&rf_units, &rflevel) != GE_NONE)
253 if (GSM->GetBatteryLevel(&batt_units, &batterylevel) != GE_NONE)
257 last_t = curr_t = time(NULL);
263 /* don't answer if we see wrong password */
264 if (strncmp(password, rq.passwd, 8) != 0) continue;
267 printf("server: received cmd Nr. %d\n",rq.cmd);
272 /* RTH FIXME: for Version 0.1, init is done at startup */
278 version.major = MG_NET_API_MAJOR_VERSION;
279 version.minor = MG_NET_API_MINOR_VERSION;
280 memcpy(rq.buffer, &version, sizeof(version));
283 /* RTH FIXME: check errors */
284 while (GSM->GetIMEI(ident.imei) != GE_NONE) sleep(1);
285 while (GSM->GetRevision(ident.rev) != GE_NONE) sleep(1);
286 while (GSM->GetModel(ident.model) != GE_NONE) sleep(1);
287 memcpy(rq.buffer, &ident, sizeof(ident));
290 case MG_MEMORYSTATUS:
291 memcpy(&status, rq.buffer, sizeof(status));
293 printf("server: getmemorystaus for %s requested\n",status.memtype);
295 if (!GetMemoryTypeID(status.memtype, &stats.MemoryType))
297 rq.cmd = -1; /* error */
300 if ( GSM->GetMemoryStatus( &stats) != GE_NONE)
302 rq.cmd = -1; /* error */
305 status.free = stats.Free;
306 status.used = stats.Used;
307 memcpy(rq.buffer, &status, sizeof(status));
309 case MG_GET_MEMORY_LOCATION:
310 memcpy(&ph, rq.buffer, sizeof(ph));
312 printf("server: getmemorylocation for %s, Location: %d requested\n",ph.memtype,ph.location);
314 ph.name[0] = ph.group[0] = ph.nr_general[0] = ph.nr_mobile[0] = ph.nr_work[0] = '\0';
315 ph.nr_fax[0] = ph.nr_home[0] = ph.note[0] = ph.postal[0] = ph.email[0] = '\0';
316 if (!GetMemoryTypeID(ph.memtype, &entry.MemoryType))
318 rq.cmd = -1; /* error */
321 entry.Location = ph.location;
322 GetMemoryTypeString(memory_type_string, &entry.MemoryType);
323 if ( GSM->GetMemoryLocation(&entry) != GE_NONE)
325 rq.cmd = -1; /* error */
328 strcpy(ph.name,entry.Name);
329 strcpy(ph.nr_general,entry.Number);
330 //strcpy(ph.group,NAMEOF:entry.group);
331 for( i = 0; i < entry.SubEntriesCount; i++ )
333 switch(entry.SubEntries[i].EntryType)
336 switch(entry.SubEntries[i].NumberType)
339 strcpy(ph.nr_mobile,entry.SubEntries[i].data.Number);
342 strcpy(ph.nr_work,entry.SubEntries[i].data.Number);
345 strcpy(ph.nr_fax,entry.SubEntries[i].data.Number);
348 strcpy(ph.nr_home,entry.SubEntries[i].data.Number);
355 strcpy(ph.note,entry.SubEntries[i].data.Number);
358 strcpy(ph.postal,entry.SubEntries[i].data.Number);
361 strcpy(ph.email,entry.SubEntries[i].data.Number);
367 memcpy(rq.buffer, &ph, sizeof(ph));
369 case MG_WRITE_PHONEBOOK_LOCATION:
370 memcpy(&ph, rq.buffer, sizeof(ph));
372 printf("server: writememorylocation for Location: %d requested\n",ph.location);
374 if (!GetMemoryTypeID(ph.memtype, &entry.MemoryType))
376 rq.cmd = -1; /* error */
379 GetMemoryTypeString(memory_type_string, &entry.MemoryType);
380 if ( GSM->GetMemoryLocation(&entry) != GE_NONE)
382 rq.cmd = -1; /* error */
385 entry.Location = ph.location;
386 entry.SubEntriesCount = 0;
387 strcpy(entry.Name,ph.name);
388 strcpy(entry.Number,ph.nr_general);
389 //if ( ph.group[0] != '\0') Version 0.3 !!
390 if ( ph.nr_mobile[0]!= '\0')
392 entry.SubEntries[entry.SubEntriesCount].EntryType = GSM_Number;
393 entry.SubEntries[entry.SubEntriesCount].NumberType = GSM_Mobile;
394 strcpy(entry.SubEntries[entry.SubEntriesCount].data.Number,ph.nr_mobile);
395 entry.SubEntriesCount++;
397 if ( ph.nr_work[0]!= '\0')
399 entry.SubEntries[entry.SubEntriesCount].EntryType = GSM_Number;
400 entry.SubEntries[entry.SubEntriesCount].NumberType = GSM_Work;
401 strcpy(entry.SubEntries[entry.SubEntriesCount].data.Number,ph.nr_work);
402 entry.SubEntriesCount++;
404 if ( ph.nr_fax[0]!= '\0')
406 entry.SubEntries[entry.SubEntriesCount].EntryType = GSM_Number;
407 entry.SubEntries[entry.SubEntriesCount].NumberType = GSM_Fax;
408 strcpy(entry.SubEntries[entry.SubEntriesCount].data.Number,ph.nr_fax);
409 entry.SubEntriesCount++;
411 if ( ph.nr_home[0]!= '\0')
413 entry.SubEntries[entry.SubEntriesCount].EntryType = GSM_Number;
414 entry.SubEntries[entry.SubEntriesCount].NumberType = GSM_Home;
415 strcpy(entry.SubEntries[entry.SubEntriesCount].data.Number,ph.nr_home);
416 entry.SubEntriesCount++;
418 if ( ph.note[0]!= '\0')
420 entry.SubEntries[entry.SubEntriesCount].EntryType = GSM_Note;
421 strcpy(entry.SubEntries[entry.SubEntriesCount].data.Number,ph.note);
422 entry.SubEntriesCount++;
424 if ( ph.postal[0]!= '\0')
426 entry.SubEntries[entry.SubEntriesCount].EntryType = GSM_Postal;
427 strcpy(entry.SubEntries[entry.SubEntriesCount].data.Number,ph.postal);
428 entry.SubEntriesCount++;
430 if ( ph.email[0]!= '\0')
432 entry.SubEntries[entry.SubEntriesCount].EntryType = GSM_Email;
433 strcpy(entry.SubEntries[entry.SubEntriesCount].data.Number,ph.email);
434 entry.SubEntriesCount++;
437 /* This is to send other exports (like from 6110) to 7110 */
438 if (!entry.SubEntriesCount) {
439 entry.SubEntriesCount = 1;
440 entry.SubEntries[0].EntryType = GSM_Number;
441 entry.SubEntries[0].NumberType = GSM_General;
442 entry.SubEntries[0].BlockNumber = 2;
443 strcpy(entry.SubEntries[0].data.Number, entry.Number);
446 if (GSM->WritePhonebookLocation(&entry) != GE_NONE)
448 rq.cmd = -1; /* error */
451 memcpy(rq.buffer, &ph, sizeof(ph));
453 case MG_DELETE_PHONEBOOK_LOCATION:
454 memcpy(&ph, rq.buffer, sizeof(ph));
456 printf("server: deletememorylocation for Location: %d requested\n",ph.location);
458 if (!GetMemoryTypeID(ph.memtype, &entry.MemoryType))
460 rq.cmd = -1; /* error */
463 GetMemoryTypeString(memory_type_string, &entry.MemoryType);
464 if ( GSM->GetMemoryLocation(&entry) != GE_NONE)
466 rq.cmd = -1; /* error */
469 entry.SubEntriesCount = 0;
470 entry.Name[0] = '\0';
471 entry.Number[0] = '\0';
472 entry.Location = ph.location;
473 if (GSM->WritePhonebookLocation(&entry) != GE_NONE)
475 rq.cmd = -1; /* error */
478 memcpy(rq.buffer, &ph, sizeof(ph));
481 memcpy(&sms, rq.buffer, sizeof(sms));
483 printf("server: sendsms to %s requested\n",sms.destination);
484 printf("server: message:%s\n",sms.message);
485 printf("server: Centerindex = %d\n",sms.SMSCenterIndex);
488 if(sms.enablevoice) SMSUDHType=GSM_EnableVoice;
489 if(sms.disablevoice) SMSUDHType=GSM_DisableVoice;
490 if(sms.enableemail) SMSUDHType=GSM_EnableEmail;
491 if(sms.disableemail) SMSUDHType=GSM_DisableEmail;
492 if(sms.enablefax) SMSUDHType=GSM_EnableFax;
493 if(sms.disablefax) SMSUDHType=GSM_DisableFax;
494 if(sms.unicode) SMSCoding=GSM_Coding_Unicode;
497 GSM_MakeMultiPartSMS2(&MultiSMS,sms.message,strlen(sms.message),SMSUDHType,SMSCoding);
498 MultiSMS.SMS[0].Class=SMSClass;
499 MultiSMS.SMS[0].ReplyViaSameSMSC=SMSReply;
500 MultiSMS.SMS[0].Type=SMSType;
503 /* Message Center index */
504 if (sms.SMSCenterIndex == 0 )
505 MultiSMS.SMS[0].MessageCenter.No = 1;
508 if (sms.SMSCenterIndex < 0 || sms.SMSCenterIndex > 5)
510 rq.cmd = -2; /* error */
513 MultiSMS.SMS[0].MessageCenter.No = sms.SMSCenterIndex;
516 /* Message Center number */
517 if(strlen(sms.SMSCNumber) > 0)
519 MultiSMS.SMS[0].MessageCenter.No = 0;
520 strcpy(MultiSMS.SMS[0].MessageCenter.Number,sms.SMSCNumber);
524 strcpy(MultiSMS.SMS[0].Destination,sms.destination);
526 /* delivery report */
527 if(sms.delivery) MultiSMS.SMS[0].Type=GST_DR;
530 if (sms.SMSValidity != 0)
531 MultiSMS.SMS[0].Validity=sms.SMSValidity;
533 MultiSMS.SMS[0].Validity=4320; /* 3 days */
535 if( GSM->SendSMSMessage(&MultiSMS.SMS[0]) != GE_SMSSENDOK )
537 rq.cmd = -3; /* error */
541 memcpy(rq.buffer, &sms, sizeof(sms));
549 sendto (s, &rq, sizeof(rq), 0, (struct sockaddr *) &clientaddr, addrlen);
550 if (rq.cmd == MG_EXIT) exit(0);
553 default: /* Parent process comes here. */