]>
cvs.zerfleddert.de Git - hmcfgusb/blob - hmland.c
8e5d6daf642c797a6f0cebdf2a2cddeab8ea6b6d
   1 /* HM-CFG-LAN emulation for HM-CFG-USB 
   3  * Copyright (c) 2013-15 Michael Gernoth <michael@gernoth.net> 
   5  * Permission is hereby granted, free of charge, to any person obtaining a copy 
   6  * of this software and associated documentation files (the "Software"), to 
   7  * deal in the Software without restriction, including without limitation the 
   8  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 
   9  * sell copies of the Software, and to permit persons to whom the Software is 
  10  * furnished to do so, subject to the following conditions: 
  12  * The above copyright notice and this permission notice shall be included in 
  13  * all copies or substantial portions of the Software. 
  15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
  16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
  17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
  18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
  19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
  20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 
  34 #include <sys/types.h> 
  35 #include <sys/socket.h> 
  39 #include <netinet/in.h> 
  40 #include <arpa/inet.h> 
  41 #include <libusb-1.0/libusb.h> 
  48 #define PID_FILE "/var/run/hmland.pid" 
  50 #define DEFAULT_REBOOT_SECONDS  86400 
  51 #define LAN_READ_CHUNK_SIZE     2048 
  52 /* Don't allow remote clients to consume all of our memory */ 
  53 #define LAN_MAX_LINE_LENGTH     4096 
  54 #define LAN_MAX_BUF_LENGTH      1048576 
  58 static int impersonate_hmlanif 
= 0; 
  60 static int verbose 
= 0; 
  61 static FILE *logfile 
= NULL
; 
  62 static int reboot_seconds 
= 0; 
  63 static int reboot_at_hour 
= -1; 
  64 static int reboot_at_minute 
= -1; 
  65 static int reboot_set 
= 0; 
  66 static uint8_t *lan_read_buf 
= NULL
; 
  67 static int lan_read_buflen 
= 0; 
  68 static char *serial 
= NULL
; 
  73         struct queued_rx 
*next
; 
  76 static struct queued_rx 
*qrx 
= NULL
; 
  77 static int wait_for_h 
= 0; 
  79 #define FLAG_LENGTH_BYTE        (1<<0) 
  80 #define FLAG_FORMAT_HEX         (1<<1) 
  81 #define FLAG_COMMA_BEFORE       (1<<2) 
  82 #define FLAG_COMMA_AFTER        (1<<3) 
  83 #define FLAG_NL                 (1<<4) 
  84 #define FLAG_IGNORE_COMMAS      (1<<5) 
  86 #define CHECK_SPACE(x)          if ((*outpos + x) > outend) { fprintf(stderr, "Not enough space!\n"); return 0; } 
  87 #define CHECK_AVAIL(x)          if ((*inpos + x) > inend) { fprintf(stderr, "Not enough input available!\n"); return 0; } 
  89 static void print_timestamp(FILE *f
) 
  95         gettimeofday(&tv
, NULL
); 
  96         tmp 
= localtime(&tv
.tv_sec
); 
  97         memset(ts
, 0, sizeof(ts
)); 
  98         strftime(ts
, sizeof(ts
)-1, "%Y-%m-%d %H:%M:%S", tmp
); 
  99         fprintf(f
, "%s.%06ld: ", ts
, tv
.tv_usec
); 
 102 static void write_log(char *buf
, int len
, char *fmt
, ...) 
 107         if ((!logfile
) && (!verbose
)) 
 111                 print_timestamp(logfile
); 
 113                 print_timestamp(stdout
); 
 118                         vfprintf(logfile
, fmt
, ap
); 
 129                 for (i 
= 0; i 
< len
; i
++) { 
 131                                 fprintf(logfile
, "%c", buf
[i
]); 
 133                                 printf("%c", buf
[i
]); 
 136                         fprintf(logfile
, "\n"); 
 144 static int format_part_out(uint8_t **inpos
, int inlen
, uint8_t **outpos
, int outlen
, int len
, int flags
) 
 146         uint8_t *buf_out 
= *outpos
; 
 147         uint8_t *outend 
= *outpos 
+ outlen
; 
 148         uint8_t *inend 
= *inpos 
+ inlen
; 
 151         if (flags 
& FLAG_COMMA_BEFORE
) { 
 157         if (flags 
& FLAG_LENGTH_BYTE
) { 
 163         if (flags 
& FLAG_FORMAT_HEX
) { 
 166                 for (i 
= 0; i 
< len
; i
++) { 
 167                         **outpos 
= nibble_to_ascii(((**inpos
) & 0xf0) >> 4); 
 169                         **outpos 
= nibble_to_ascii(((**inpos
) & 0xf)); 
 170                         *inpos 
+= 1; *outpos 
+= 1; 
 175                 memcpy(*outpos
, *inpos
, len
); 
 180         if (flags 
& FLAG_COMMA_AFTER
) { 
 186         if (flags 
& FLAG_NL
) { 
 194         return *outpos 
- buf_out
; 
 197 static int parse_part_in(uint8_t **inpos
, int inlen
, uint8_t **outpos
, int outlen
, int flags
) 
 199         uint8_t *buf_out 
= *outpos
; 
 200         uint8_t *outend 
= *outpos 
+ outlen
; 
 201         uint8_t *inend 
= *inpos 
+ inlen
; 
 203         if (flags 
& FLAG_LENGTH_BYTE
) { 
 211                                 if (!(flags 
& FLAG_IGNORE_COMMAS
)) 
 220                 **outpos 
= (len 
/ 2); 
 224         while(*inpos 
< inend
) { 
 225                 if (**inpos 
== ',') { 
 227                         if (!(flags 
& FLAG_IGNORE_COMMAS
)) 
 236                 **outpos 
= ascii_to_nibble(**inpos
) << 4; 
 238                 **outpos 
|= ascii_to_nibble(**inpos
); 
 239                 *inpos 
+= 1; *outpos 
+= 1; 
 242         return *outpos 
- buf_out
; 
 245 static int hmlan_format_out(uint8_t *buf
, int buf_len
, void *data
) 
 251         int fd 
= *((int*)data
); 
 257         memset(out
, 0, sizeof(out
)); 
 261         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 1, 0); 
 264                         if (impersonate_hmlanif
) { 
 269                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 0, FLAG_LENGTH_BYTE
); 
 270                         version 
= inpos
[0] << 8; 
 272                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 2, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 273                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 0, FLAG_COMMA_BEFORE 
| FLAG_LENGTH_BYTE
); 
 274                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 3, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 275                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 3, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 276                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 4, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 277                         if (version 
< 0x03c7) { 
 278                                 format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 2, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE 
| FLAG_NL
); 
 280                                 format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 2, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 281                                 format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 1, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE 
| FLAG_NL
); 
 285                                 int new_reboot_seconds
; 
 287                                 if (version 
< 0x03c7) { 
 288                                         new_reboot_seconds 
= DEFAULT_REBOOT_SECONDS
; 
 290                                         new_reboot_seconds 
= 0; 
 293                                 if (verbose 
&& new_reboot_seconds 
&& (reboot_seconds 
!= new_reboot_seconds
)) 
 294                                         printf("Rebooting in %u seconds due to old firmware (0.%d)\n", 
 295                                                 new_reboot_seconds
, version
); 
 297                                 reboot_seconds 
= new_reboot_seconds
; 
 302                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 3, FLAG_FORMAT_HEX
); 
 303                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 2, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 304                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 4, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 305                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 1, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 306                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 2, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 307                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 0, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE 
| FLAG_LENGTH_BYTE 
| FLAG_NL
); 
 311                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 4, FLAG_FORMAT_HEX
); 
 312                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 2, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 313                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 4, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 314                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 1, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 315                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 2, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 316                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 0, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE 
| FLAG_LENGTH_BYTE 
| FLAG_NL
); 
 320                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 1, FLAG_FORMAT_HEX
); 
 321                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 1, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 322                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 1, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE
); 
 323                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 1, FLAG_FORMAT_HEX 
| FLAG_COMMA_BEFORE 
| FLAG_NL
); 
 327                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 1, FLAG_FORMAT_HEX 
| FLAG_NL
); 
 331                         format_part_out(&inpos
, (buf_len
-(inpos
-buf
)), &outpos
, (sizeof(out
)-(outpos
-out
)), buf_len
-1, FLAG_FORMAT_HEX 
| FLAG_NL
); 
 332                         hexdump(buf
, buf_len
, "Unknown> "); 
 336         /* Queue packet until first respone to 'K' is received */ 
 337         if (wait_for_h 
&& buf
[0] != 'H') { 
 338                 struct queued_rx 
**rxp 
= &qrx
; 
 341                         rxp 
= &((*rxp
)->next
); 
 343                 *rxp 
= malloc(sizeof(struct queued_rx
)); 
 349                 memset(*rxp
, 0, sizeof(struct queued_rx
)); 
 350                 (*rxp
)->len 
= outpos
-out
; 
 351                 (*rxp
)->rx 
= malloc((*rxp
)->len
); 
 356                 memset((*rxp
)->rx
, 0, (*rxp
)->len
); 
 357                 memcpy((*rxp
)->rx
, out
, (*rxp
)->len
); 
 362         write_log((char*)out
, outpos
-out
-2, "LAN < "); 
 364         w 
= write(fd
, out
, outpos
-out
); 
 370         /* Send all queued packets */ 
 372                 struct queued_rx 
*curr_rx 
= qrx
; 
 373                 struct queued_rx 
*last_rx
; 
 376                         write_log(curr_rx
->rx
, curr_rx
->len
-2, "LAN < "); 
 378                         w 
= write(fd
, curr_rx
->rx
, curr_rx
->len
); 
 383                         curr_rx 
= curr_rx
->next
; 
 397 static int hmlan_parse_one(uint8_t *cmd
, int last
, void *data
) 
 399         struct hmcfgusb_dev 
*dev 
= data
; 
 400         uint8_t out
[0x40]; //FIXME!!! 
 402         uint8_t *inpos 
= cmd
; 
 409         write_log((char*)cmd
, last
,  "LAN > "); 
 411         memset(out
, 0, sizeof(out
)); 
 412         *outpos
++ = *inpos
++; 
 416                         parse_part_in(&inpos
, (last
-(inpos
-cmd
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 0); 
 417                         parse_part_in(&inpos
, (last
-(inpos
-cmd
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 0); 
 418                         parse_part_in(&inpos
, (last
-(inpos
-cmd
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 0); 
 419                         parse_part_in(&inpos
, (last
-(inpos
-cmd
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 0); 
 420                         parse_part_in(&inpos
, (last
-(inpos
-cmd
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 0); 
 421                         parse_part_in(&inpos
, (last
-(inpos
-cmd
)), &outpos
, (sizeof(out
)-(outpos
-out
)), FLAG_LENGTH_BYTE
); 
 424                         parse_part_in(&inpos
, (last
-(inpos
-cmd
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 0); 
 425                         parse_part_in(&inpos
, (last
-(inpos
-cmd
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 0); 
 426                         parse_part_in(&inpos
, (last
-(inpos
-cmd
)), &outpos
, (sizeof(out
)-(outpos
-out
)), FLAG_LENGTH_BYTE
); 
 429                         parse_part_in(&inpos
, (last
-(inpos
-cmd
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 0); 
 430                         parse_part_in(&inpos
, (last
-(inpos
-cmd
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 0); 
 431                         parse_part_in(&inpos
, (last
-(inpos
-cmd
)), &outpos
, (sizeof(out
)-(outpos
-out
)), 0); 
 432                         parse_part_in(&inpos
, (last
-(inpos
-cmd
)), &outpos
, (sizeof(out
)-(outpos
-out
)), FLAG_LENGTH_BYTE
); 
 434                         parse_part_in(&inpos
, (last
-(inpos
-cmd
)), &outpos
, (sizeof(out
)-(outpos
-out
)), FLAG_IGNORE_COMMAS
); 
 438         hmcfgusb_send(dev
, out
, sizeof(out
), 1); 
 443 static int hmlan_parse_in(int fd
, void *data
) 
 449         newbuf 
= realloc(lan_read_buf
, lan_read_buflen 
+ LAN_READ_CHUNK_SIZE
); 
 454         lan_read_buf 
= newbuf
; 
 455         r 
= read(fd
, lan_read_buf 
+ lan_read_buflen
, LAN_READ_CHUNK_SIZE
); 
 457                 lan_read_buflen 
+= r
; 
 458                 if (lan_read_buflen 
> LAN_MAX_BUF_LENGTH
) { 
 460                                 printf("Our buffer is bigger than %d bytes (%d bytes), closing connection!\n", LAN_MAX_BUF_LENGTH
, lan_read_buflen
); 
 463                 while(lan_read_buflen 
> 0) { 
 466                         for (i 
= 0; i 
< lan_read_buflen
; i
++) { 
 467                                 if ((lan_read_buf
[i
] == '\r') || (lan_read_buf
[i
] == '\n')) { 
 469                                                 hmlan_parse_one(lan_read_buf
, i
, data
); 
 470                                         memmove(lan_read_buf
, lan_read_buf 
+ i 
+ 1, lan_read_buflen 
- (i 
+ 1)); 
 471                                         lan_read_buflen 
-= (i 
+ 1); 
 475                                 if (i 
> LAN_MAX_LINE_LENGTH
) { 
 477                                                 printf("Client sent more than %d bytes without newline, closing connection!\n", LAN_MAX_LINE_LENGTH
); 
 483                         newbuf 
= realloc(lan_read_buf
, lan_read_buflen
); 
 484                         if (lan_read_buflen 
&& !newbuf
) { 
 488                         lan_read_buf 
= newbuf
; 
 491                 if (errno 
!= ECONNRESET
) 
 501 static int comm(int fd_in
, int fd_out
, int master_socket
, int flags
) 
 503         struct hmcfgusb_dev 
*dev
; 
 504         uint8_t out
[0x40]; //FIXME!!! 
 507         hmcfgusb_set_debug(debug
); 
 509         dev 
= hmcfgusb_init(hmlan_format_out
, &fd_out
, serial
); 
 511                 fprintf(stderr
, "Can't initialize HM-CFG-USB!\n"); 
 515         if (dev
->bootloader
) { 
 517                         printf("HM-CFG-USB in bootloader mode, restarting in normal mode...\n"); 
 519                 hmcfgusb_leave_bootloader(dev
); 
 526         if ((reboot_at_hour 
!= -1) && (reboot_at_minute 
!= -1)) { 
 531                 tm_s 
= localtime(&tm
); 
 537                 tm_s
->tm_hour 
= reboot_at_hour
; 
 538                 tm_s
->tm_min 
= reboot_at_minute
; 
 542                 reboot_seconds 
= tm 
- dev
->opened_at
; 
 544                 while (reboot_seconds 
<= 0) 
 545                         reboot_seconds 
+= 86400; 
 548         if (verbose 
&& reboot_seconds
) 
 549                 printf("Rebooting in %u seconds\n", reboot_seconds
); 
 552         if (!hmcfgusb_add_pfd(dev
, fd_in
, POLLIN
)) { 
 553                 fprintf(stderr
, "Can't add client to pollfd!\n"); 
 558         if (master_socket 
>= 0) { 
 559                 if (!hmcfgusb_add_pfd(dev
, master_socket
, POLLIN
)) { 
 560                         fprintf(stderr
, "Can't add master_socket to pollfd!\n"); 
 566         memset(out
, 0, sizeof(out
)); 
 569         hmcfgusb_send_null_frame(dev
, 1); 
 570         hmcfgusb_send(dev
, out
, sizeof(out
), 1); 
 575                 fd 
= hmcfgusb_poll(dev
, 1000);  /* Wakeup device/bus at least once a second */ 
 577                         if (fd 
== master_socket
) { 
 580                                 client 
= accept(master_socket
, NULL
, 0); 
 582                                         shutdown(client
, SHUT_RDWR
); 
 586                                 if (hmlan_parse_in(fd
, dev
) <= 0) { 
 590                 } else if (fd 
== -1) { 
 592                                 if (errno 
!= ETIMEDOUT
) { 
 593                                         perror("hmcfgusb_poll"); 
 596                                         /* periodically wakeup the device */ 
 597                                         hmcfgusb_send_null_frame(dev
, 1); 
 599                                                 memset(out
, 0, sizeof(out
)); 
 601                                                 hmcfgusb_send(dev
, out
, sizeof(out
), 1); 
 607                 if (reboot_seconds 
&& ((dev
->opened_at 
+ reboot_seconds
) <= time(NULL
))) { 
 609                                 printf("HM-CFG-USB running since %lu seconds, rebooting now...\n", 
 610                                         time(NULL
) - dev
->opened_at
); 
 612                         hmcfgusb_enter_bootloader(dev
); 
 620 void sigterm_handler(int sig
) 
 622         if (unlink(PID_FILE
) == -1) 
 623                 perror("Can't remove PID file"); 
 628 #define FLAG_DAEMON     (1 << 0) 
 629 #define FLAG_PID_FILE   (1 << 1) 
 631 static int socket_server(char *iface
, int port
, int flags
) 
 633         struct sigaction sact
; 
 634         struct sockaddr_in sin
; 
 639         if (flags 
& FLAG_DAEMON
) { 
 640                 FILE *pidfile 
= NULL
; 
 642                 if (flags 
& FLAG_PID_FILE
) { 
 645                         fd 
= open(PID_FILE
, O_CREAT 
| O_EXCL 
| O_WRONLY
, 0644); 
 647                                 if (errno 
== EEXIST
) { 
 649                                         pidfile 
= fopen(PID_FILE
, "r"); 
 651                                                 perror("PID file " PID_FILE 
" already exists, already running?"); 
 655                                         if (fscanf(pidfile
, "%u", &old_pid
) != 1) { 
 657                                                 fprintf(stderr
, "Can't read old PID from " PID_FILE 
", already running?\n"); 
 663                                         fprintf(stderr
, "Already running with PID %u according to " PID_FILE 
"!\n", old_pid
); 
 666                                 perror("Can't create PID file " PID_FILE
); 
 670                         pidfile 
= fdopen(fd
, "w"); 
 672                                 perror("Can't reopen PID file fd"); 
 676                         memset(&sact
, 0, sizeof(sact
)); 
 677                         sact
.sa_handler 
= sigterm_handler
; 
 679                         if (sigaction(SIGTERM
, &sact
, NULL
) == -1) { 
 680                                 perror("sigaction(SIGTERM)"); 
 688                                 fprintf(pidfile
, "%u\n", pid
); 
 692                         printf("Daemon with PID %u started!\n", pid
); 
 694                 } else if (pid 
< 0) { 
 703         memset(&sact
, 0, sizeof(sact
)); 
 704         sact
.sa_handler 
= SIG_IGN
; 
 706         if (sigaction(SIGPIPE
, &sact
, NULL
) == -1) { 
 707                 perror("sigaction(SIGPIPE)"); 
 711         sock 
= socket(PF_INET
, SOCK_STREAM
, IPPROTO_TCP
); 
 713                 perror("Can't open socket"); 
 718         if (setsockopt(sock
, SOL_SOCKET
, SO_REUSEADDR
, &n
, sizeof(n
)) == -1) { 
 719                 perror("Can't set socket options"); 
 723         memset(&sin
, 0, sizeof(sin
)); 
 724         sin
.sin_family 
= AF_INET
; 
 725         sin
.sin_port 
= htons(port
); 
 727                 sin
.sin_addr
.s_addr 
= htonl(INADDR_ANY
); 
 729                 if (inet_pton(AF_INET
, iface
, &(sin
.sin_addr
.s_addr
)) != 1) { 
 730                         fprintf(stderr
, "Can't convert IP %s, aborting!\n", iface
); 
 735         if (bind(sock
, (struct sockaddr
*)&sin
, sizeof(sin
)) == -1) { 
 736                 perror("Can't bind socket"); 
 740         if (listen(sock
, 1) == -1) { 
 741                 perror("Can't listen on socket"); 
 746                 struct sockaddr_in csin
; 
 749                 in_addr_t client_addr
; 
 751                 memset(&csin
, 0, sizeof(csin
)); 
 752                 csinlen 
= sizeof(csin
); 
 753                 client 
= accept(sock
, (struct sockaddr
*)&csin
, &csinlen
); 
 755                         perror("Couldn't accept client"); 
 759                 /* FIXME: getnameinfo... */ 
 760                 client_addr 
= ntohl(csin
.sin_addr
.s_addr
); 
 762                 write_log(NULL
, 0, "Client %d.%d.%d.%d connected!\n", 
 763                                 (client_addr 
& 0xff000000) >> 24, 
 764                                 (client_addr 
& 0x00ff0000) >> 16, 
 765                                 (client_addr 
& 0x0000ff00) >> 8, 
 766                                 (client_addr 
& 0x000000ff)); 
 768                 comm(client
, client
, sock
, flags
); 
 770                 shutdown(client
, SHUT_RDWR
); 
 778                 write_log(NULL
, 0, "Connection to %d.%d.%d.%d closed!\n", 
 779                                 (client_addr 
& 0xff000000) >> 24, 
 780                                 (client_addr 
& 0x00ff0000) >> 16, 
 781                                 (client_addr 
& 0x0000ff00) >> 8, 
 782                                 (client_addr 
& 0x000000ff)); 
 789 static int interactive_server(int flags
) 
 791         if (!comm(STDIN_FILENO
, STDOUT_FILENO
, -1, flags
)) 
 797 void hmlan_syntax(char *prog
) 
 799         fprintf(stderr
, "Syntax: %s options\n\n", prog
); 
 800         fprintf(stderr
, "Possible options:\n"); 
 801         fprintf(stderr
, "\t-D\t\tdebug mode\n"); 
 802         fprintf(stderr
, "\t-d\t\tdaemon mode\n"); 
 803         fprintf(stderr
, "\t-h\t\tthis help\n"); 
 804         fprintf(stderr
, "\t-I\t\tpretend to be HM-LAN-IF for compatibility with client-software (previous default)\n"); 
 805         fprintf(stderr
, "\t-i\t\tinteractive mode (connect HM-CFG-USB to terminal)\n"); 
 806         fprintf(stderr
, "\t-l ip\t\tlisten on given IP address only (for example 127.0.0.1)\n"); 
 807         fprintf(stderr
, "\t-L logfile\tlog network-communication to logfile\n"); 
 808         fprintf(stderr
, "\t-P\t\tcreate PID file " PID_FILE 
" in daemon mode\n"); 
 809         fprintf(stderr
, "\t-p n\t\tlisten on port n (default: 1000)\n"); 
 810         fprintf(stderr
, "\t-r n\t\treboot HM-CFG-USB after n seconds (0: no reboot, default: %u if FW < 0.967, 0 otherwise)\n", DEFAULT_REBOOT_SECONDS
); 
 811         fprintf(stderr
, "\t   hh:mm\treboot HM-CFG-USB daily at hh:mm\n"); 
 812         fprintf(stderr
, "\t-S serial\tuse HM-CFG-USB with given serial (for multiple hmland instances)\n"); 
 813         fprintf(stderr
, "\t-v\t\tverbose mode\n"); 
 814         fprintf(stderr
, "\t-V\t\tshow version (" VERSION 
")\n"); 
 818 int main(int argc
, char **argv
) 
 827         while((opt 
= getopt(argc
, argv
, "DdhIiPp:Rr:l:L:S:vV")) != -1) { 
 834                                 flags 
|= FLAG_DAEMON
; 
 837                                 impersonate_hmlanif 
= 1; 
 843                                 flags 
|= FLAG_PID_FILE
; 
 846                                 port 
= strtoul(optarg
, &ep
, 10); 
 848                                         fprintf(stderr
, "Can't parse port!\n"); 
 853                                 fprintf(stderr
, "-R is no longer needed (1s wakeup is default)\n"); 
 856                                 reboot_seconds 
= strtoul(optarg
, &ep
, 10); 
 859                                                 reboot_at_hour 
= reboot_seconds
; 
 861                                                 reboot_at_minute 
= strtoul(ep
, &ep
, 10); 
 863                                                         fprintf(stderr
, "Can't parse reboot-time!\n"); 
 869                                                 fprintf(stderr
, "Can't parse reboot-timeout!\n"); 
 879                                 logfile 
= fopen(optarg
, "a"); 
 881                                         perror("fopen(logfile)"); 
 892                                 printf("hmland " VERSION 
"\n"); 
 893                                 printf("Copyright (c) 2013-15 Michael Gernoth\n\n"); 
 899                                 hmlan_syntax(argv
[0]); 
 906                 return interactive_server(flags
); 
 908                 return socket_server(iface
, port
, flags
);