Conditional (enabled) compilation of Nokia Authentication phase (not needed?)
[gnokii.git] / mgnetd / mgnetd.c
1 /*
2
3   G N O K I I
4
5   A Linux/Unix toolset and driver for Nokia mobile phones.
6
7   Released under the terms of the GNU GPL, see file COPYING for more details.
8
9   Mainline code for mgnetd daemon.
10
11   Last modification: 07.02.2002
12   Ralf Thelen <ralf@mythelen.de>        
13
14 */
15
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <signal.h>
19 #include <string.h>
20 #include <ctype.h>
21 #include <time.h>
22 #include <sys/stat.h>
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <sys/errno.h>
26 #include <netinet/in.h>
27 #include <netdb.h>
28  
29 #if defined(__svr4__) || defined(__FreeBSD__)
30   #  include <strings.h>        /* for bzero */
31 #endif
32  
33 #include <unistd.h>
34 #include <termios.h>
35 #include <fcntl.h>
36 #include <sys/types.h>
37 #include <sys/time.h>
38 #include <getopt.h>
39
40 #include "misc.h"
41 #include "files/cfgreader.h"
42 #include "gsm-common.h"
43 #include "gsm-api.h"
44 #include "mgnetd.h"
45
46 #ifdef USE_NLS
47   #include <locale.h>
48 #endif
49
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 */ 
57
58
59 void usage(void)
60 {
61
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"));
66   exit(1);
67 }
68
69 /* fbusinit is the generic function which waits for the FBUS link. The limit
70    is 10 seconds. After 10 seconds we quit. */
71  
72 void fbusinit(void (*rlp_handler)(RLP_F96Frame *frame))
73 {
74  
75   int count=0;
76   GSM_Error error;
77
78 #ifndef WIN32
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);
81 #endif
82  
83   /* Initialise the code for the GSM interface. */
84   error = GSM_Initialise(Model, Port, Initlength, GetConnectionTypeFromString(Connection), rlp_handler, SynchronizeTime);
85  
86   if (error != GE_NONE) {
87     fprintf(stderr, _("GSM/FBUS init failed! (Unknown model ?). Quitting.\n"));
88     exit(-1);
89   }
90  
91   /* First (and important!) wait for GSM link to be active. We allow 10
92      seconds... */
93   while (count++ < 200 && *GSM_LinkOK == false)
94     usleep(50000);
95  
96   if (*GSM_LinkOK == false) {
97     fprintf (stderr, _("Hmmm... GSM_LinkOK never went true. Quitting.\n"));
98     exit(-1);
99   }
100 }
101
102
103 /* 
104         main
105         simple udp-based server
106  */
107 int main(int argc, char *argv[])
108 {
109
110 MG_api_request rq;
111 MG_rq_version version;
112 MG_rq_identify ident;
113 MG_rq_memorystatus status;
114 MG_rq_phonebook_location ph;
115 MG_rq_send_sms sms;
116
117 GSM_PhonebookEntry entry;
118 GSM_MemoryStatus stats;
119 GSM_RFUnits rf_units = GRF_Arbitrary;
120 GSM_BatteryUnits batt_units = GBU_Arbitrary;
121
122 GSM_MultiSMSMessage MultiSMS;
123 GSM_SMSMessageType SMSType=GST_SMS;
124 int SMSClass = -1;
125 bool SMSReply = false;
126 GSM_Coding_Type SMSCoding = GSM_Coding_Default;
127 GSM_UDH SMSUDHType = GSM_NoUDH;
128
129 char password[8];
130
131 char memory_type_string[20];
132
133 float rflevel=-1, batterylevel=-1;
134
135 time_t curr_t, last_t;
136
137 int s;                          /* socket descriptor */
138 int cc;                         /* contains the number of bytes read */
139
140 struct servent *sp;             /* pointer to service information */
141
142 struct sockaddr_in myaddr;      /* for local socket address */
143 struct sockaddr_in clientaddr;  /* for client's socket address */
144
145 extern int errno;               /* for unblocking io */  
146
147 int addrlen;
148 int error_cnt = 0;
149 int i;
150
151 /* For GNU gettext */
152 #ifdef USE_NLS
153   textdomain("gnokii");
154   setlocale(LC_ALL, "pl_PL"); //here is string for Polish localisation
155 #endif
156  
157     /* Read config file */
158     if (CFG_ReadConfig(&Model, &Port, &Initlength, &Connection, &BinDir, &SynchronizeTime,false) < 0) {
159         exit(-1);
160     }
161  
162 /* Handle command line arguments. */
163 if (argc != 2) usage();
164
165 /* get password from commandline */
166 strncpy(password,argv[1],8);
167
168
169 /* init timevars */
170 curr_t = last_t = time(NULL);
171
172 /* clear out address structures */
173 memset ((char *)&myaddr, 0, sizeof(struct sockaddr_in));
174 memset ((char *)&clientaddr, 0, sizeof(struct sockaddr_in));
175
176 /* Set up address structure for the socket. */
177 myaddr.sin_family = AF_INET;
178 myaddr.sin_addr.s_addr = INADDR_ANY;
179
180 sp = getservbyname ("mygnokii", "udp");
181         if (sp == NULL) {
182 #ifdef DEBUG
183                 printf("mygnokii not found in /etc/services\n");
184                 printf("using default port 50963\n");
185 #endif
186          myaddr.sin_port = htons(50963);
187         }
188         else myaddr.sin_port = sp->s_port;
189
190
191         /* Create the socket. */
192         s = socket (AF_INET, SOCK_DGRAM, 0);
193         if (s == -1) {
194                 perror(argv[0]);
195                 printf("%s: unable to create socket\n", argv[0]);
196                 exit(1);
197         }
198
199         /* Bind the server's address to the socket. */
200         if (bind(s, (struct sockaddr *) &myaddr, sizeof(struct sockaddr)) == -1) {
201                 perror(argv[0]);
202                 printf("%s: unable to bind address\n", argv[0]);
203                 exit(1);
204         }
205
206         /* Make socket unblocking */
207         if ( fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
208                 perror(argv[0]);
209                 printf("%s: unable to make socket unblocking\n", argv[0]);
210                 exit(1);
211         }
212
213
214         setpgrp();
215
216         switch (fork()) {
217         case -1:                /* Unable to fork, for some reason. */
218                 perror(argv[0]);
219                 printf("%s: unable to fork daemon\n", argv[0]);
220                 exit(1);
221
222         case 0: 
223
224                 /* init GSM Interface */
225                 fbusinit(NULL);
226                 printf("init done, daemonizing\n");
227
228 #ifndef DEBUG
229                 close(0);
230                 close(1);
231                 close(2);
232 #endif
233
234                 for(;;) {
235                         addrlen = sizeof(struct sockaddr_in);
236
237                         cc = recvfrom(s, &rq, sizeof(rq), 0,
238                                                 (struct sockaddr *) &clientaddr, &addrlen);
239
240                         if ( cc == -1)
241                          {
242                           if ( errno != EAGAIN) exit(1);
243                           else
244                            {    /* no data -> do some usefull things */
245                                 /* required for infrared connections to prevent timeouts */
246                                 curr_t = time(NULL);
247                                 if ( difftime(curr_t, last_t) > 5 )
248                                   {
249                                    if (GSM->GetRFLevel(&rf_units, &rflevel) != GE_NONE)
250                                          error_cnt++;
251                                    else
252                                          error_cnt=0;
253                                    if (GSM->GetBatteryLevel(&batt_units, &batterylevel) != GE_NONE)
254                                          error_cnt++;
255                                    else
256                                          error_cnt=0;
257                                    last_t = curr_t = time(NULL);
258                                   }
259                                 continue;
260                                 }
261                            }/* if( cc == -1) */
262
263                         /* don't answer if we see wrong password */
264                         if (strncmp(password, rq.passwd, 8) != 0) continue;
265
266 #ifdef DEBUG
267         printf("server: received cmd Nr. %d\n",rq.cmd);
268 #endif
269                         switch (rq.cmd) 
270                                 {
271                                         case MG_INIT:   
272                                                         /* RTH FIXME: for Version 0.1, init is done at startup */
273                                                         break;
274                                         case MG_EXIT:   
275                                                         GSM->Terminate();
276                                                         break;
277                                         case MG_VERSION:
278                                                         version.major = MG_NET_API_MAJOR_VERSION;
279                                                         version.minor = MG_NET_API_MINOR_VERSION;
280                                                         memcpy(rq.buffer, &version, sizeof(version));
281                                                         break;
282                                         case MG_IDENTIFY:
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));
288                                                         break;
289
290                                         case MG_MEMORYSTATUS:
291                                                         memcpy(&status, rq.buffer, sizeof(status));
292 #ifdef DEBUG
293         printf("server: getmemorystaus for %s requested\n",status.memtype);
294 #endif
295                                                         if (!GetMemoryTypeID(status.memtype, &stats.MemoryType))
296                                                                  {
297                                                                   rq.cmd = -1; /* error */
298                                                                   break;
299                                                                  }
300                                                         if ( GSM->GetMemoryStatus( &stats) != GE_NONE)
301                                                                  {
302                                                                   rq.cmd = -1; /* error */
303                                                                   break;
304                                                                  }
305                                                         status.free = stats.Free;
306                                                         status.used = stats.Used;
307                                                         memcpy(rq.buffer, &status, sizeof(status));
308                                                         break;
309                                         case MG_GET_MEMORY_LOCATION:
310                                                         memcpy(&ph, rq.buffer, sizeof(ph));
311 #ifdef DEBUG
312         printf("server: getmemorylocation for %s, Location: %d requested\n",ph.memtype,ph.location);
313 #endif
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))
317                                                                  {
318                                                                   rq.cmd = -1; /* error */
319                                                                   break;
320                                                                  }
321                                                         entry.Location = ph.location;
322                                                         GetMemoryTypeString(memory_type_string, &entry.MemoryType);
323                                                         if ( GSM->GetMemoryLocation(&entry) != GE_NONE)
324                                                                  {
325                                                                   rq.cmd = -1; /* error */
326                                                                   break;
327                                                                  }
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++ )
332                                                         {
333                                                          switch(entry.SubEntries[i].EntryType)
334                                                          {
335                                                           case GSM_Number:
336                                                                 switch(entry.SubEntries[i].NumberType)
337                                                                 {
338                                                                  case GSM_Mobile:
339                                                                         strcpy(ph.nr_mobile,entry.SubEntries[i].data.Number);
340                                                                         break;
341                                                                  case GSM_Work:
342                                                                         strcpy(ph.nr_work,entry.SubEntries[i].data.Number);
343                                                                         break;
344                                                                  case GSM_Fax:
345                                                                         strcpy(ph.nr_fax,entry.SubEntries[i].data.Number);
346                                                                         break;
347                                                                  case GSM_Home:
348                                                                         strcpy(ph.nr_home,entry.SubEntries[i].data.Number);
349                                                                         break;
350                                                                  default:
351                                                                         break;
352                                                                 }
353                                                                 break;
354                                                           case GSM_Note:
355                                                                 strcpy(ph.note,entry.SubEntries[i].data.Number);
356                                                                 break;
357                                                           case GSM_Postal:
358                                                                 strcpy(ph.postal,entry.SubEntries[i].data.Number);
359                                                                 break;
360                                                           case GSM_Email:
361                                                                 strcpy(ph.email,entry.SubEntries[i].data.Number);
362                                                                 break;
363                                                           default:
364                                                                 break;
365                                                          }
366                                                         }//for
367                                                         memcpy(rq.buffer, &ph, sizeof(ph));
368                                                         break;
369                                         case MG_WRITE_PHONEBOOK_LOCATION:
370                                                         memcpy(&ph, rq.buffer, sizeof(ph));
371 #ifdef DEBUG
372         printf("server: writememorylocation for Location: %d requested\n",ph.location);
373 #endif
374                                                         if (!GetMemoryTypeID(ph.memtype, &entry.MemoryType))
375                                                                  {
376                                                                   rq.cmd = -1; /* error */
377                                                                   break;
378                                                                  }
379                                                         GetMemoryTypeString(memory_type_string, &entry.MemoryType);
380                                                         if ( GSM->GetMemoryLocation(&entry) != GE_NONE)
381                                                                  {
382                                                                   rq.cmd = -1; /* error */
383                                                                   break;
384                                                                  }
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')
391                                                         {  
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++;
396                                                         }
397                                                         if ( ph.nr_work[0]!= '\0')
398                                                         {  
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++;
403                                                         }
404                                                         if ( ph.nr_fax[0]!= '\0')
405                                                         {  
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++;
410                                                         }
411                                                         if ( ph.nr_home[0]!= '\0')
412                                                         {  
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++;
417                                                         }
418                                                         if ( ph.note[0]!= '\0')
419                                                         {  
420                                                          entry.SubEntries[entry.SubEntriesCount].EntryType = GSM_Note;
421                                                          strcpy(entry.SubEntries[entry.SubEntriesCount].data.Number,ph.note);
422                                                          entry.SubEntriesCount++;
423                                                         }
424                                                         if ( ph.postal[0]!= '\0')
425                                                         {  
426                                                          entry.SubEntries[entry.SubEntriesCount].EntryType = GSM_Postal;
427                                                          strcpy(entry.SubEntries[entry.SubEntriesCount].data.Number,ph.postal);
428                                                          entry.SubEntriesCount++;
429                                                         }
430                                                         if ( ph.email[0]!= '\0')
431                                                         {  
432                                                          entry.SubEntries[entry.SubEntriesCount].EntryType = GSM_Email;
433                                                          strcpy(entry.SubEntries[entry.SubEntriesCount].data.Number,ph.email);
434                                                          entry.SubEntriesCount++;
435                                                         }
436
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);
444                                                         }
445
446                                                         if (GSM->WritePhonebookLocation(&entry) != GE_NONE)
447                                                         {
448                                                           rq.cmd = -1; /* error */
449                                                           break;
450                                                         }
451                                                         memcpy(rq.buffer, &ph, sizeof(ph));
452                                                         break;
453                                         case MG_DELETE_PHONEBOOK_LOCATION:
454                                                         memcpy(&ph, rq.buffer, sizeof(ph));
455 #ifdef DEBUG
456         printf("server: deletememorylocation for Location: %d requested\n",ph.location);
457 #endif
458                                                         if (!GetMemoryTypeID(ph.memtype, &entry.MemoryType))
459                                                                  {
460                                                                   rq.cmd = -1; /* error */
461                                                                   break;
462                                                                  }
463                                                         GetMemoryTypeString(memory_type_string, &entry.MemoryType);
464                                                         if ( GSM->GetMemoryLocation(&entry) != GE_NONE)
465                                                                  {
466                                                                   rq.cmd = -1; /* error */
467                                                                   break;
468                                                                  }
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)
474                                                         {
475                                                           rq.cmd = -1; /* error */
476                                                           break;
477                                                         }
478                                                         memcpy(rq.buffer, &ph, sizeof(ph));
479                                                         break;
480                                         case MG_SEND_SMS:
481                                                         memcpy(&sms, rq.buffer, sizeof(sms));
482 #ifdef DEBUG
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);
486 #endif
487                                                         /* options */
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;
495
496                                                         /* message */
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;
501
502
503                                                         /* Message Center index */
504                                                         if (sms.SMSCenterIndex == 0 ) 
505                                                                 MultiSMS.SMS[0].MessageCenter.No = 1;
506                                                         else
507                                                            {
508                                                                 if (sms.SMSCenterIndex < 0 || sms.SMSCenterIndex > 5)
509                                                                 {
510                                                                  rq.cmd = -2; /* error */
511                                                                  break;
512                                                                 }
513                                                                 MultiSMS.SMS[0].MessageCenter.No = sms.SMSCenterIndex;
514                                                            }
515
516                                                         /* Message Center number */
517                                                         if(strlen(sms.SMSCNumber) > 0)
518                                                                 {
519                                                                  MultiSMS.SMS[0].MessageCenter.No = 0;
520                                                                  strcpy(MultiSMS.SMS[0].MessageCenter.Number,sms.SMSCNumber);
521                                                                 }
522
523                                                         /* destination  */
524                                                         strcpy(MultiSMS.SMS[0].Destination,sms.destination);
525
526                                                         /* delivery report */
527                                                         if(sms.delivery)  MultiSMS.SMS[0].Type=GST_DR;
528
529                                                         /* validity  */
530                                                         if (sms.SMSValidity != 0)
531                                                            MultiSMS.SMS[0].Validity=sms.SMSValidity;
532                                                         else
533                                                            MultiSMS.SMS[0].Validity=4320; /* 3 days */
534
535                                                         if(  GSM->SendSMSMessage(&MultiSMS.SMS[0]) != GE_SMSSENDOK )
536                                                         {
537                                                           rq.cmd = -3; /* error */
538                                                           break;
539                                                         }
540
541                                                         memcpy(rq.buffer, &sms, sizeof(sms));
542                                                         break;
543                                         default:        
544                                                         rq.cmd = -1;
545                                                         break;
546
547                                 }
548
549                         sendto (s, &rq, sizeof(rq), 0, (struct sockaddr *) &clientaddr, addrlen);
550                         if (rq.cmd == MG_EXIT) exit(0);
551                 }
552
553         default:                /* Parent process comes here. */
554                 exit(0);
555         }
556 }