OSDN Git Service

Adding all files as MASTER
[icmpsh/icmpsh.git] / utils.c
1 /*
2  * Copyright (c) 2006  Tsuyoshi SAKAMOTO <skmt.free@gmail.com>,
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in
13  *    the documentation and/or other materials provided with the
14  *    distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
19  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
20  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
23  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
26  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
27  * DAMAGE.
28 */
29
30
31 /********************************************
32  * include file
33  ********************************************
34 */
35 #include "icmpsh.h"
36
37 #include <stdio.h>
38 #include <strings.h>
39 #include <unistd.h>
40 #include <stdlib.h>
41
42 #include <errno.h>
43
44 #include <syslog.h>
45 #include <stdarg.h>
46
47 #include <string.h>
48 #include <sys/types.h>
49 #include <sys/time.h>
50
51 #include <termios.h>
52 #include <sys/ioctl.h>
53 #include <arpa/inet.h>
54
55 #include <errno.h>
56
57 #include <signal.h>
58 #include <sys/wait.h>
59
60
61 /********************************************
62  * macro
63  ********************************************
64 */
65
66
67 /********************************************
68  * type definition
69  ********************************************
70 */
71
72
73 /********************************************
74  * global variable
75  ********************************************
76 */
77 extern int debug;
78
79
80 /* syslog */
81 const int level[] = {
82         LOG_EMERG,
83         LOG_ALERT,
84         LOG_CRIT,
85         LOG_ERR,
86         LOG_WARNING,
87         LOG_NOTICE,
88         LOG_INFO,
89         LOG_DEBUG,
90         0       /* syslog off */
91 };
92
93
94 /********************************************
95  * proto type
96  ********************************************
97 */
98
99 /* public */
100
101 #ifdef SOLARIS
102 void cfmakeraw(struct termios *);
103 #endif
104
105 int ic_select(int, long);
106 void ic_plog(int, const char *, ...);
107 void ic_log(const char *, ...);
108 void ic_recv_ntohs(ic_data *);
109 void ic_set_termios(net_termios *, struct termios *);
110 void ic_set_winsz(net_winsz *, struct winsize *);
111 void ic_get_termios(struct termios *, net_termios *);
112 void ic_get_winsz(struct winsize *, net_winsz *);
113 void ic_set_data(ic_data *, u_char, u_char, u_short, u_char *, int);
114 void ic_set_header(ic_data *, u_char, u_char, u_short, u_short);
115
116 ssize_t xread(int, void *, size_t);
117 ssize_t xwrite(int, void *, size_t);
118
119 void vsys_err(int, const char *, ...);
120 void vsys(int, const char *, ...);
121
122 u_short xchecksum(u_short *, int);
123
124 pid_t xfork(void);
125
126 void *xmalloc(size_t);
127 void *xrealloc(void *, size_t);
128
129 char *xstrdup(char *);
130
131
132 /* local */
133 static int xselect(int, fd_set *, fd_set *, fd_set *, struct timeval *);
134
135
136 /*============================================================================
137  * program section
138  *============================================================================
139 */
140
141 #ifdef SOLARIS
142 /*-------------------------------------------------------------------------
143  * cfmakeraw for Solaris
144  *
145  *-------------------------------------------------------------------------
146 */
147 void
148 cfmakeraw(struct termios *t)
149 {
150         memset(t, 0, sizeof(struct termios));
151
152         t->c_iflag |= IGNBRK;
153         t->c_cflag |= CS8|CREAD;
154         t->c_cc[VMIN] = 1;
155         t->c_cc[VTIME] = 0;
156
157         return;
158 }
159 #endif
160
161 /*-------------------------------------------------------------------------
162  * termios and window size
163  *
164  *-------------------------------------------------------------------------
165 */
166 void
167 ic_set_termios(net_termios *pn, struct termios *pt) {
168         int i;
169         pn->c_iflag   = htonl(pt->c_iflag);
170         pn->c_oflag   = htonl(pt->c_oflag);
171         pn->c_cflag   = htonl(pt->c_cflag);
172         pn->c_lflag   = htonl(pt->c_lflag);
173 #ifndef SOLARIS
174         pn->c_ispeed  = htonl(pt->c_ispeed);
175         pn->c_ospeed  = htonl(pt->c_ospeed);
176 #endif
177         for (i = 0; i < NCCS; ++i) {
178                 pn->c_cc[i] = pt->c_cc[i];
179         }
180         return;
181 }
182
183 void
184 ic_set_winsz(net_winsz *pn, struct winsize *pt) {
185         pn->ws_row     = htons(pt->ws_row);
186         pn->ws_col     = htons(pt->ws_col);
187         pn->ws_xpixel  = htons(pt->ws_xpixel);
188         pn->ws_ypixel  = htons(pt->ws_ypixel);
189         return;
190 }
191
192 void
193 ic_get_termios(struct termios *pt, net_termios *pn) {
194         int i;
195         pt->c_iflag   = ntohl(pn->c_iflag);
196         pt->c_oflag   = ntohl(pn->c_oflag);
197         pt->c_cflag   = ntohl(pn->c_cflag);
198         pt->c_lflag   = ntohl(pn->c_lflag);
199 #ifndef SOLARIS
200         pt->c_ispeed  = ntohl(pn->c_ispeed);
201         pt->c_ospeed  = ntohl(pn->c_ospeed);
202 #endif
203         for (i = 0; i < NCCS; ++i) { 
204                 pt->c_cc[i] = pn->c_cc[i];              
205         }       
206         return;         
207
208
209 void
210 ic_get_winsz(struct winsize *pt, net_winsz *pn) {
211         pt->ws_row     = ntohs(pn->ws_row);
212         pt->ws_col     = ntohs(pn->ws_col);
213         pt->ws_xpixel  = ntohs(pn->ws_xpixel);
214         pt->ws_ypixel  = ntohs(pn->ws_ypixel);
215         return;
216 }
217
218
219 /*-------------------------------------------------------------------------
220  * debug log handler
221  *
222  *-------------------------------------------------------------------------
223 */
224 void
225 ic_plog(int lvl, const char *format, ...) {
226         va_list ap;
227         va_start(ap, format);
228
229         if (debug) {
230                 vfprintf(stderr, format, ap);
231                 fprintf(stderr, "\n");
232         }
233         else {
234                 if (level[lvl])
235                         vsyslog(level[lvl], format, ap);
236         }
237
238         va_end(ap);
239
240         return;
241 }
242
243 void
244 ic_log(const char *format, ...) {
245         va_list ap;
246         va_start(ap, format);
247
248         if (debug) {
249                 vfprintf(stderr, format, ap);
250                 fprintf(stderr, "\n");
251         }
252
253         va_end(ap);
254
255         return;
256 }
257
258 /*-------------------------------------------------------------------------
259  * convert net to host byte order
260  *
261  *-------------------------------------------------------------------------
262 */
263 void
264 ic_recv_ntohs(ic_data *pic) {
265         char *p;
266         struct ip *piph;
267         icmp_echo *picmph;
268         ic_header *pich;
269
270         p       = (char *)pic;
271         piph    = (struct ip *)p;
272         picmph  = (icmp_echo *)(p + (IC_IPHLWRS * 4));
273         pich    = (ic_header *)(p + (IC_IPHLWRS * 4) + sizeof(icmp_echo));
274
275         picmph->id    = ntohs(picmph->id);
276         picmph->seq   = ntohs(picmph->seq);
277         pich->length  = ntohs(pich->length);
278
279         return;
280 }
281
282
283 /*-------------------------------------------------------------------------
284  * select with error check
285  *    arg: follow select()'s interface
286  *    ret: >=0(success), -1(failure)
287  *-------------------------------------------------------------------------
288 */
289 int
290 xselect(int nfd, fd_set *rfd, fd_set *wfd, fd_set *ofd, struct timeval *pt) {
291         int n;
292
293         for (;;) {
294                 if ((n = select(nfd, rfd, wfd, ofd, pt)) < 0) {
295                         if (errno == EINTR)
296                                 continue;
297                 }
298                 else
299                         break;
300         }
301
302         return (n);
303 }
304
305 /*
306  * common select interface for icmsh
307 */
308 int
309 ic_select(int nfd, long timeout) {
310         int n;
311         struct timeval tv, *ptv;
312         fd_set rfd;
313
314         memset(&rfd, 0, sizeof(rfd));
315         tv.tv_sec  = timeout;
316         tv.tv_usec = 0;
317
318         ptv = &tv;
319         for (;;) {
320                 FD_ZERO(&rfd);
321                 FD_SET(nfd, &rfd);
322                 if ((n = xselect(nfd + 1, &rfd, NULL, NULL, ptv)) < 0) {
323                         break;
324                 }
325                 else if (n == 0) {
326                         break;
327                 }
328                 if (FD_ISSET(nfd, &rfd))
329                         break;
330         }
331
332         return (n);
333 }
334
335
336 /*-------------------------------------------------------------------------
337  * ic_data common interface
338  *
339  *
340  *-------------------------------------------------------------------------
341 */
342 void
343 ic_set_data(ic_data *p, u_char type, u_char flag, u_short length, u_char *buf, int bufsz) {
344         u_char *ppay = (u_char *)&(p->data.payload[0]) + sizeof(ic_header);
345         p->data.ich.type    = type;
346         p->data.ich.flag    = flag;
347         p->data.ich.length  = htons(length);
348         if (buf)
349                 strncpy((char *)ppay, (char *)buf, bufsz);
350         return;
351 }
352
353 void
354 ic_set_header(ic_data *p, u_char type, u_char code, u_short id, u_short seq) {
355         p->icmph.type   = type;
356         p->icmph.code   = code;
357         p->icmph.id     = htons(id);
358         p->icmph.seq    = htons(seq);
359         p->icmph.cksum  = xchecksum((u_short *)&(p->icmph), IC_DATASIZE);
360         return;
361 }
362
363
364 /*-------------------------------------------------------------------------
365  * send / wait signal
366  *
367  *-------------------------------------------------------------------------
368 */
369 int
370 ic_kill(char *proc, pid_t p, int sig) {
371         int rc;
372         if ((rc = kill(p, sig)) != 0)
373                 ic_plog(SINF, "(%s) kill failure (%s)", proc, strerror(errno));
374
375         return (rc);
376 }
377
378 pid_t
379 ic_waitpid(char *proc, pid_t p, int *status, int options) {
380         pid_t wpid;
381         if ((wpid = waitpid(p, status, options)) < 0)
382                 ic_plog(SINF, "(%s) waitpid failure (%s)", proc, strerror(errno));
383
384         return (wpid);
385 }
386
387
388 /*-------------------------------------------------------------------------
389  * read with error check
390  *
391  *-------------------------------------------------------------------------
392 */
393 ssize_t
394 xread(int fd, void *buff, size_t size)
395 {
396         size_t left;
397         ssize_t nread;
398
399         void *p;
400
401         p = buff;
402         left = size;
403
404         while (left > 0) {
405                 if ((nread = read(fd, p, left)) < 0) {
406                         if (errno == EINTR)
407                                 nread = 0;
408                         else
409                                 return (-1);
410                 }
411                 else if (nread == 0) {
412                         break;
413                 }
414                 left -= nread;
415                 p = (char *)p + nread;
416         }
417
418         return (size - left);
419 }
420
421
422 /*-------------------------------------------------------------------------
423  * write with error check
424  *
425  *-------------------------------------------------------------------------
426 */
427 ssize_t
428 xwrite(int fd, void *buff, size_t size)
429 {
430         size_t left;
431         ssize_t nwrite;
432
433         void *p;
434
435         p = buff;
436         left = size;
437
438         while (left > 0) {
439                 if ((nwrite = write(fd, p, left)) < 0) {
440                         if (errno == EINTR)
441                                 nwrite = 0;
442                         else
443                                 return (-1);
444                 }
445                 left -= nwrite;
446                 p = (char *)p + nwrite;
447         }
448
449         return size;
450 }
451
452
453 /*-------------------------------------------------------------------------
454  * syslog interface
455  *
456  *-------------------------------------------------------------------------
457 */
458 void
459 vsys_err(int priority, const char *format, ...)
460 {
461         va_list ap;
462
463         va_start(ap, format);
464         vsyslog(priority, format, ap);
465
466         va_end(ap);
467
468         exit(1);
469 }
470
471 void
472 vsys(int priority, const char *format, ...)
473 {
474         va_list ap;
475
476         va_start(ap, format);
477         vsyslog(priority, format, ap);
478
479         va_end(ap);
480
481         return;
482 }
483
484
485 /*-------------------------------------------------------------------------
486  * internet checksum
487  *
488  *-------------------------------------------------------------------------
489 */
490 u_short
491 xchecksum(u_short *addr, int len) {
492         u_short answer;
493         u_short *w;
494         int nleft, sum;
495
496         nleft = len;
497         sum = 0;
498         w = addr;
499         while (nleft > 1) {
500                 sum += *(w++);
501                 nleft -= 2;
502         }
503         if (nleft == 1)
504                 sum += *(u_char *) w;
505
506         sum = (sum & 0xffff) + (sum >> 16);
507         sum += (sum >> 16);
508         answer = ~sum;
509
510         return (answer);
511 }
512
513
514 /*-------------------------------------------------------------------------
515  * fork with error check
516  *
517  *-------------------------------------------------------------------------
518 */
519 pid_t
520 xfork(void)
521 {
522         pid_t pid;
523
524         if ((pid = fork()) < 0)
525                 exit(1);
526
527         return (pid);
528 }
529
530
531 /*-------------------------------------------------------------------------
532  * malloc family with error check
533  *
534  *-------------------------------------------------------------------------
535 */
536 void *
537 xmalloc(size_t size)
538 {
539         void *tmp;
540
541         if (!size)
542                 exit (1);
543
544         if ((tmp = malloc(size)) == NULL)
545                 exit (1);
546         else
547                 memset(tmp, 0, size);
548
549         return (tmp);
550 }
551
552 void *
553 xrealloc(void *src, size_t size)
554 {
555         void *dst;
556
557         if (!size)
558                 exit (1);
559
560         if ((dst = realloc(src, size)) == NULL)
561                 exit (1);
562
563         return (dst);
564 }
565
566
567 /*-------------------------------------------------------------------------
568  * strdup with error check
569  *
570  *-------------------------------------------------------------------------
571 */
572 char *
573 xstrdup(char *ptr)
574 {
575         char *tmp;
576
577         if (!ptr)
578                 exit (1);
579
580         if ((tmp = strdup(ptr)) == NULL)
581                 exit (1);
582
583         return (tmp);
584 }
585
586
587 /* end of source */