summaryrefslogtreecommitdiff
path: root/jni/src/common.c (plain)
blob: 6e63d3ac35651e369f4d1b9ec21a448bb64ecd5d
1/***********************************************************************
2*
3* common.c
4*
5* Implementation of user-space PPPoE redirector for Linux.
6*
7* Common functions used by PPPoE client and server
8*
9* Copyright (C) 2000 by Roaring Penguin Software Inc.
10*
11* This program may be distributed according to the terms of the GNU
12* General Public License, version 2 or (at your option) any later version.
13*
14* LIC: GPL
15*
16***********************************************************************/
17
18static char const RCSID[] =
19"$Id$";
20/* For vsnprintf prototype */
21#define _ISOC99_SOURCE 1
22
23/* For seteuid prototype */
24#define _BSD_SOURCE 1
25
26#include "pppoe.h"
27
28
29#ifdef HAVE_SYSLOG_H
30#include <syslog.h>
31#include <android/log.h>
32#define syslog(prio, fmt...) \
33 __android_log_print(prio, "PPPOE", fmt)
34#endif
35
36#include <string.h>
37#include <errno.h>
38#include <stdlib.h>
39#include <stdarg.h>
40
41#ifdef HAVE_UNISTD_H
42#include <unistd.h>
43#endif
44
45#include <sys/types.h>
46#include <pwd.h>
47
48#include "../../ppp/pppd/pathnames.h"
49/* Are we running SUID or SGID? */
50int IsSetID = 0;
51
52static uid_t saved_uid = -2;
53static uid_t saved_gid = -2;
54
55/**********************************************************************
56*%FUNCTION: parsePacket
57*%ARGUMENTS:
58* packet -- the PPPoE discovery packet to parse
59* func -- function called for each tag in the packet
60* extra -- an opaque data pointer supplied to parsing function
61*%RETURNS:
62* 0 if everything went well; -1 if there was an error
63*%DESCRIPTION:
64* Parses a PPPoE discovery packet, calling "func" for each tag in the packet.
65* "func" is passed the additional argument "extra".
66***********************************************************************/
67int
68parsePacket(PPPoEPacket *packet, ParseFunc *func, void *extra)
69{
70 UINT16_t len = ntohs(packet->length);
71 unsigned char *curTag;
72 UINT16_t tagType, tagLen;
73
74 if (packet->ver != 1) {
75 syslog(LOG_ERR, "Invalid PPPoE version (%d)", (int) packet->ver);
76 return -1;
77 }
78 if (packet->type != 1) {
79 syslog(LOG_ERR, "Invalid PPPoE type (%d)", (int) packet->type);
80 return -1;
81 }
82
83 /* Do some sanity checks on packet */
84 if (len > ETH_DATA_LEN - 6) { /* 6-byte overhead for PPPoE header */
85 syslog(LOG_ERR, "Invalid PPPoE packet length (%u)", len);
86 return -1;
87 }
88
89 /* Step through the tags */
90 curTag = packet->payload;
91 while(curTag - packet->payload < len) {
92 /* Alignment is not guaranteed, so do this by hand... */
93 tagType = (((UINT16_t) curTag[0]) << 8) +
94 (UINT16_t) curTag[1];
95 tagLen = (((UINT16_t) curTag[2]) << 8) +
96 (UINT16_t) curTag[3];
97 if (tagType == TAG_END_OF_LIST) {
98 return 0;
99 }
100 if ((curTag - packet->payload) + tagLen + TAG_HDR_SIZE > len) {
101 syslog(LOG_ERR, "Invalid PPPoE tag length (%u)", tagLen);
102 return -1;
103 }
104 func(tagType, tagLen, curTag+TAG_HDR_SIZE, extra);
105 curTag = curTag + TAG_HDR_SIZE + tagLen;
106 }
107 return 0;
108}
109
110/**********************************************************************
111*%FUNCTION: findTag
112*%ARGUMENTS:
113* packet -- the PPPoE discovery packet to parse
114* type -- the type of the tag to look for
115* tag -- will be filled in with tag contents
116*%RETURNS:
117* A pointer to the tag if one of the specified type is found; NULL
118* otherwise.
119*%DESCRIPTION:
120* Looks for a specific tag type.
121***********************************************************************/
122unsigned char *
123findTag(PPPoEPacket *packet, UINT16_t type, PPPoETag *tag)
124{
125 UINT16_t len = ntohs(packet->length);
126 unsigned char *curTag;
127 UINT16_t tagType, tagLen;
128
129 if (packet->ver != 1) {
130 syslog(LOG_ERR, "Invalid PPPoE version (%d)", (int) packet->ver);
131 return NULL;
132 }
133 if (packet->type != 1) {
134 syslog(LOG_ERR, "Invalid PPPoE type (%d)", (int) packet->type);
135 return NULL;
136 }
137
138 /* Do some sanity checks on packet */
139 if (len > ETH_DATA_LEN - 6) { /* 6-byte overhead for PPPoE header */
140 syslog(LOG_ERR, "Invalid PPPoE packet length (%u)", len);
141 return NULL;
142 }
143
144 /* Step through the tags */
145 curTag = packet->payload;
146 while(curTag - packet->payload < len) {
147 /* Alignment is not guaranteed, so do this by hand... */
148 tagType = (((UINT16_t) curTag[0]) << 8) +
149 (UINT16_t) curTag[1];
150 tagLen = (((UINT16_t) curTag[2]) << 8) +
151 (UINT16_t) curTag[3];
152 if (tagType == TAG_END_OF_LIST) {
153 return NULL;
154 }
155 if ((curTag - packet->payload) + tagLen + TAG_HDR_SIZE > len) {
156 syslog(LOG_ERR, "Invalid PPPoE tag length (%u)", tagLen);
157 return NULL;
158 }
159 if (tagType == type) {
160 memcpy(tag, curTag, tagLen + TAG_HDR_SIZE);
161 return curTag;
162 }
163 curTag = curTag + TAG_HDR_SIZE + tagLen;
164 }
165 return NULL;
166}
167
168/**********************************************************************
169*%FUNCTION: switchToRealID
170*%ARGUMENTS:
171* None
172*%RETURNS:
173* Nothing
174*%DESCRIPTION:
175* Sets effective user-ID and group-ID to real ones. Aborts on failure
176***********************************************************************/
177void
178switchToRealID (void) {
179 if (IsSetID) {
180 if ((int)saved_uid < 0) saved_uid = geteuid();
181 if ((int)saved_gid < 0) saved_gid = getegid();
182 if (setegid(getgid()) < 0) {
183 printErr("setgid failed");
184 exit(EXIT_FAILURE);
185 }
186 if (seteuid(getuid()) < 0) {
187 printErr("seteuid failed");
188 exit(EXIT_FAILURE);
189 }
190 }
191}
192
193/**********************************************************************
194*%FUNCTION: switchToEffectiveID
195*%ARGUMENTS:
196* None
197*%RETURNS:
198* Nothing
199*%DESCRIPTION:
200* Sets effective user-ID and group-ID back to saved gid/uid
201***********************************************************************/
202void
203switchToEffectiveID (void) {
204 if (IsSetID) {
205 if (setegid(saved_gid) < 0) {
206 printErr("setgid failed");
207 exit(EXIT_FAILURE);
208 }
209 if (seteuid(saved_uid) < 0) {
210 printErr("seteuid failed");
211 exit(EXIT_FAILURE);
212 }
213 }
214}
215
216/**********************************************************************
217*%FUNCTION: dropPrivs
218*%ARGUMENTS:
219* None
220*%RETURNS:
221* Nothing
222*%DESCRIPTION:
223* If effective ID is root, try to become "nobody". If that fails and
224* we're SUID, switch to real user-ID
225***********************************************************************/
226void
227dropPrivs(void)
228{
229 struct passwd *pw = NULL;
230 int ok = 0;
231 if (geteuid() == 0) {
232 pw = getpwnam("nobody");
233 if (pw) {
234 if (setgid(pw->pw_gid) < 0) ok++;
235 if (setuid(pw->pw_uid) < 0) ok++;
236 }
237 }
238 if (ok < 2 && IsSetID) {
239 setegid(getgid());
240 seteuid(getuid());
241 }
242}
243
244/**********************************************************************
245*%FUNCTION: printErr
246*%ARGUMENTS:
247* str -- error message
248*%RETURNS:
249* Nothing
250*%DESCRIPTION:
251* Prints a message to stderr and syslog.
252***********************************************************************/
253void
254printErr(char const *str)
255{
256 syslog(LOG_ERR, "%s", str);
257}
258
259
260/**********************************************************************
261*%FUNCTION: strDup
262*%ARGUMENTS:
263* str -- string to copy
264*%RETURNS:
265* A malloc'd copy of str. Exits if malloc fails.
266***********************************************************************/
267char *
268strDup(char const *str)
269{
270 char *copy = malloc(strlen(str)+1);
271 if (!copy) {
272 rp_fatal("strdup failed");
273 }
274 strcpy(copy, str);
275 return copy;
276}
277
278/**********************************************************************
279*%FUNCTION: computeTCPChecksum
280*%ARGUMENTS:
281* ipHdr -- pointer to IP header
282* tcpHdr -- pointer to TCP header
283*%RETURNS:
284* The computed TCP checksum
285***********************************************************************/
286UINT16_t
287computeTCPChecksum(unsigned char *ipHdr, unsigned char *tcpHdr)
288{
289 UINT32_t sum = 0;
290 UINT16_t count = ipHdr[2] * 256 + ipHdr[3];
291 UINT16_t tmp;
292
293 unsigned char *addr = tcpHdr;
294 unsigned char pseudoHeader[12];
295
296 /* Count number of bytes in TCP header and data */
297 count -= (ipHdr[0] & 0x0F) * 4;
298
299 memcpy(pseudoHeader, ipHdr+12, 8);
300 pseudoHeader[8] = 0;
301 pseudoHeader[9] = ipHdr[9];
302 pseudoHeader[10] = (count >> 8) & 0xFF;
303 pseudoHeader[11] = (count & 0xFF);
304
305 /* Checksum the pseudo-header */
306 sum += * (UINT16_t *) pseudoHeader;
307 sum += * ((UINT16_t *) (pseudoHeader+2));
308 sum += * ((UINT16_t *) (pseudoHeader+4));
309 sum += * ((UINT16_t *) (pseudoHeader+6));
310 sum += * ((UINT16_t *) (pseudoHeader+8));
311 sum += * ((UINT16_t *) (pseudoHeader+10));
312
313 /* Checksum the TCP header and data */
314 while (count > 1) {
315 memcpy(&tmp, addr, sizeof(tmp));
316 sum += (UINT32_t) tmp;
317 addr += sizeof(tmp);
318 count -= sizeof(tmp);
319 }
320 if (count > 0) {
321 sum += (unsigned char) *addr;
322 }
323
324 while(sum >> 16) {
325 sum = (sum & 0xffff) + (sum >> 16);
326 }
327 return (UINT16_t) ((~sum) & 0xFFFF);
328}
329
330/**********************************************************************
331*%FUNCTION: clampMSS
332*%ARGUMENTS:
333* packet -- PPPoE session packet
334* dir -- either "incoming" or "outgoing"
335* clampMss -- clamp value
336*%RETURNS:
337* Nothing
338*%DESCRIPTION:
339* Clamps MSS option if TCP SYN flag is set.
340***********************************************************************/
341void
342clampMSS(PPPoEPacket *packet, char const *dir, int clampMss)
343{
344 unsigned char *tcpHdr;
345 unsigned char *ipHdr;
346 unsigned char *opt;
347 unsigned char *endHdr;
348 unsigned char *mssopt = NULL;
349 UINT16_t csum;
350
351 int len, minlen;
352
353 /* check PPP protocol type */
354 if (packet->payload[0] & 0x01) {
355 /* 8 bit protocol type */
356
357 /* Is it IPv4? */
358 if (packet->payload[0] != 0x21) {
359 /* Nope, ignore it */
360 return;
361 }
362
363 ipHdr = packet->payload + 1;
364 minlen = 41;
365 } else {
366 /* 16 bit protocol type */
367
368 /* Is it IPv4? */
369 if (packet->payload[0] != 0x00 ||
370 packet->payload[1] != 0x21) {
371 /* Nope, ignore it */
372 return;
373 }
374
375 ipHdr = packet->payload + 2;
376 minlen = 42;
377 }
378
379 /* Is it too short? */
380 len = (int) ntohs(packet->length);
381 if (len < minlen) {
382 /* 20 byte IP header; 20 byte TCP header; at least 1 or 2 byte PPP protocol */
383 return;
384 }
385
386 /* Verify once more that it's IPv4 */
387 if ((ipHdr[0] & 0xF0) != 0x40) {
388 return;
389 }
390
391 /* Is it a fragment that's not at the beginning of the packet? */
392 if ((ipHdr[6] & 0x1F) || ipHdr[7]) {
393 /* Yup, don't touch! */
394 return;
395 }
396 /* Is it TCP? */
397 if (ipHdr[9] != 0x06) {
398 return;
399 }
400
401 /* Get start of TCP header */
402 tcpHdr = ipHdr + (ipHdr[0] & 0x0F) * 4;
403
404 /* Is SYN set? */
405 if (!(tcpHdr[13] & 0x02)) {
406 return;
407 }
408
409 /* Compute and verify TCP checksum -- do not touch a packet with a bad
410 checksum */
411 csum = computeTCPChecksum(ipHdr, tcpHdr);
412 if (csum) {
413 syslog(LOG_ERR, "Bad TCP checksum %x", (unsigned int) csum);
414
415 /* Upper layers will drop it */
416 return;
417 }
418
419 /* Look for existing MSS option */
420 endHdr = tcpHdr + ((tcpHdr[12] & 0xF0) >> 2);
421 opt = tcpHdr + 20;
422 while (opt < endHdr) {
423 if (!*opt) break; /* End of options */
424 switch(*opt) {
425 case 1:
426 opt++;
427 break;
428
429 case 2:
430 if (opt[1] != 4) {
431 /* Something fishy about MSS option length. */
432 syslog(LOG_ERR,
433 "Bogus length for MSS option (%u) from %u.%u.%u.%u",
434 (unsigned int) opt[1],
435 (unsigned int) ipHdr[12],
436 (unsigned int) ipHdr[13],
437 (unsigned int) ipHdr[14],
438 (unsigned int) ipHdr[15]);
439 return;
440 }
441 mssopt = opt;
442 break;
443 default:
444 if (opt[1] < 2) {
445 /* Someone's trying to attack us? */
446 syslog(LOG_ERR,
447 "Bogus TCP option length (%u) from %u.%u.%u.%u",
448 (unsigned int) opt[1],
449 (unsigned int) ipHdr[12],
450 (unsigned int) ipHdr[13],
451 (unsigned int) ipHdr[14],
452 (unsigned int) ipHdr[15]);
453 return;
454 }
455 opt += (opt[1]);
456 break;
457 }
458 /* Found existing MSS option? */
459 if (mssopt) break;
460 }
461
462 /* If MSS exists and it's low enough, do nothing */
463 if (mssopt) {
464 unsigned mss = mssopt[2] * 256 + mssopt[3];
465 if (mss <= (unsigned int)clampMss) {
466 return;
467 }
468
469 mssopt[2] = (((unsigned) clampMss) >> 8) & 0xFF;
470 mssopt[3] = ((unsigned) clampMss) & 0xFF;
471 } else {
472 /* No MSS option. Don't add one; we'll have to use 536. */
473 return;
474 }
475
476 /* Recompute TCP checksum */
477 tcpHdr[16] = 0;
478 tcpHdr[17] = 0;
479 csum = computeTCPChecksum(ipHdr, tcpHdr);
480 (* (UINT16_t *) (tcpHdr+16)) = csum;
481}
482
483/***********************************************************************
484*%FUNCTION: sendPADT
485*%ARGUMENTS:
486* conn -- PPPoE connection
487* msg -- if non-NULL, extra error message to include in PADT packet.
488*%RETURNS:
489* Nothing
490*%DESCRIPTION:
491* Sends a PADT packet
492***********************************************************************/
493void
494sendPADT(PPPoEConnection *conn, char const *msg)
495{
496 PPPoEPacket packet;
497 unsigned char *cursor = packet.payload;
498
499 UINT16_t plen = 0;
500
501 /* Do nothing if no session established yet */
502 if (!conn->session) return;
503
504 /* Do nothing if no discovery socket */
505 if (conn->discoverySocket < 0) return;
506
507 memcpy(packet.ethHdr.h_dest, conn->peerEth, ETH_ALEN);
508 memcpy(packet.ethHdr.h_source, conn->myEth, ETH_ALEN);
509
510 packet.ethHdr.h_proto = htons(Eth_PPPOE_Discovery);
511 packet.ver = 1;
512 packet.type = 1;
513 packet.code = CODE_PADT;
514 packet.session = conn->session;
515
516 /* Reset Session to zero so there is no possibility of
517 recursive calls to this function by any signal handler */
518 conn->session = 0;
519
520 /* If we're using Host-Uniq, copy it over */
521 if (conn->useHostUniq) {
522 PPPoETag hostUniq;
523 pid_t pid = getpid();
524 hostUniq.type = htons(TAG_HOST_UNIQ);
525 hostUniq.length = htons(sizeof(pid));
526 memcpy(hostUniq.payload, &pid, sizeof(pid));
527 memcpy(cursor, &hostUniq, sizeof(pid) + TAG_HDR_SIZE);
528 cursor += sizeof(pid) + TAG_HDR_SIZE;
529 plen += sizeof(pid) + TAG_HDR_SIZE;
530 }
531
532 /* Copy error message */
533 if (msg) {
534 PPPoETag err;
535 size_t elen = strlen(msg);
536 err.type = htons(TAG_GENERIC_ERROR);
537 err.length = htons(elen);
538 strcpy((char *) err.payload, msg);
539 memcpy(cursor, &err, elen + TAG_HDR_SIZE);
540 cursor += elen + TAG_HDR_SIZE;
541 plen += elen + TAG_HDR_SIZE;
542 }
543
544 /* Copy cookie and relay-ID if needed */
545 if (conn->cookie.type) {
546 CHECK_ROOM(cursor, packet.payload,
547 ntohs(conn->cookie.length) + TAG_HDR_SIZE);
548 memcpy(cursor, &conn->cookie, ntohs(conn->cookie.length) + TAG_HDR_SIZE);
549 cursor += ntohs(conn->cookie.length) + TAG_HDR_SIZE;
550 plen += ntohs(conn->cookie.length) + TAG_HDR_SIZE;
551 }
552
553 if (conn->relayId.type) {
554 CHECK_ROOM(cursor, packet.payload,
555 ntohs(conn->relayId.length) + TAG_HDR_SIZE);
556 memcpy(cursor, &conn->relayId, ntohs(conn->relayId.length) + TAG_HDR_SIZE);
557 cursor += ntohs(conn->relayId.length) + TAG_HDR_SIZE;
558 plen += ntohs(conn->relayId.length) + TAG_HDR_SIZE;
559 }
560
561 packet.length = htons(plen);
562 sendPacket(conn, conn->discoverySocket, &packet, (int) (plen + HDR_SIZE));
563#ifdef DEBUGGING_ENABLED
564 if (conn->debugFile) {
565 dumpPacket(conn->debugFile, &packet, "SENT");
566 fprintf(conn->debugFile, "\n");
567 fflush(conn->debugFile);
568 }
569#endif
570 syslog(LOG_INFO,"Sent PADT");
571}
572
573
574int
575getRawSocket(char const *ifname)
576{
577 int ret;
578 int optval=1;
579 int fd;
580 struct ifreq ifr;
581 int domain, stype;
582
583 struct sockaddr_ll sa;
584
585 memset(&sa, 0, sizeof(sa));
586
587 domain = PF_PACKET;
588 stype = SOCK_RAW;
589
590 fd = socket(domain, stype, htons(ETH_PPPOE_DISCOVERY));
591 if (fd < 0) {
592 syslog(LOG_INFO,"failed to create raw socket");
593 return -1;
594 }
595
596 ret = setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval));
597 if (ret < 0) {
598 syslog(LOG_INFO,"failed to setsockopt");
599 return -1;
600 }
601
602
603 /* Get interface index */
604 sa.sll_family = AF_PACKET;
605 sa.sll_protocol = htons(ETH_PPPOE_DISCOVERY);
606
607 strncpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
608 ret = ioctl(fd, SIOCGIFINDEX, &ifr);
609 if (ret < 0) {
610 syslog(LOG_INFO,"failed to ioctl");
611 return -1;
612 }
613 sa.sll_ifindex = ifr.ifr_ifindex;
614
615 /* We're only interested in packets on specified interface */
616 ret = bind(fd, (struct sockaddr *) &sa, sizeof(sa));
617 if (ret < 0) {
618 syslog(LOG_INFO,"failed to bind");
619 return -1;
620 }
621
622 return fd;
623}
624
625
626void
627sendSavedPADT(char *padt_file)
628{
629 FILE *file_fd = NULL;
630 char *packet;
631 long len;
632 int fd;
633
634 file_fd = fopen(padt_file, "r");
635 if (!file_fd) {
636 syslog(LOG_INFO,"failed to read padt");
637 return;
638 }
639
640 fseek(file_fd, 0, SEEK_END);
641 len = ftell(file_fd);
642 if (len < 0) {
643 goto free_file_fd;
644 }
645
646 packet = malloc(len);
647 if (!packet){
648 syslog(LOG_INFO, "sendSavedPADT: failed to malloc");
649 goto free_file_fd;
650 }
651
652 fseek(file_fd, 0, SEEK_SET);
653 fread(packet, 1, len, file_fd);
654
655 fd = getRawSocket("eth0");
656 if ( fd < 0){
657 syslog(LOG_INFO, "sendSavedPADT: failed to getRawSocket");
658 goto free_packet;
659
660 }
661 send( fd, packet, len, 0);
662 syslog(LOG_INFO, "Send SavedPADT(fd = %d) by eth0", fd);
663
664 close(fd);
665
666free_packet:
667 free(packet);
668
669free_file_fd:
670 fclose(file_fd);
671 }
672
673
674void
675savePADT(PPPoEConnection *conn, char const *msg)
676{
677 FILE *padt_file_bin = NULL;
678 PPPoEPacket packet;
679 unsigned char *cursor = packet.payload;
680
681 UINT16_t plen = 0;
682
683 memcpy(packet.ethHdr.h_dest, conn->peerEth, ETH_ALEN);
684 memcpy(packet.ethHdr.h_source, conn->myEth, ETH_ALEN);
685
686 packet.ethHdr.h_proto = htons(Eth_PPPOE_Discovery);
687 packet.ver = 1;
688 packet.type = 1;
689 packet.code = CODE_PADT;
690 packet.session = conn->session;
691
692 /* Reset Session to zero so there is no possibility of
693 recursive calls to this function by any signal handler */
694 //conn->session = 0;
695
696 /* If we're using Host-Uniq, copy it over */
697 if (conn->useHostUniq) {
698 PPPoETag hostUniq;
699 pid_t pid = getpid();
700 hostUniq.type = htons(TAG_HOST_UNIQ);
701 hostUniq.length = htons(sizeof(pid));
702 memcpy(hostUniq.payload, &pid, sizeof(pid));
703 memcpy(cursor, &hostUniq, sizeof(pid) + TAG_HDR_SIZE);
704 cursor += sizeof(pid) + TAG_HDR_SIZE;
705 plen += sizeof(pid) + TAG_HDR_SIZE;
706 }
707
708 /* Copy error message */
709 if (msg) {
710 PPPoETag err;
711 size_t elen = strlen(msg);
712 err.type = htons(TAG_GENERIC_ERROR);
713 err.length = htons(elen);
714 strcpy((char *) err.payload, msg);
715 memcpy(cursor, &err, elen + TAG_HDR_SIZE);
716 cursor += elen + TAG_HDR_SIZE;
717 plen += elen + TAG_HDR_SIZE;
718 }
719
720 packet.length = htons(plen);
721
722 padt_file_bin = fopen(_ROOT_PATH "/etc/ppp/padt_bin", "w");
723 if (!padt_file_bin) {
724 syslog(LOG_INFO,"failed to save padt_bin");
725 }
726 fwrite(&packet, (int) (plen + HDR_SIZE), 1, padt_file_bin);
727 fflush(padt_file_bin);
728 fclose(padt_file_bin);
729}
730
731/***********************************************************************
732*%FUNCTION: sendPADTf
733*%ARGUMENTS:
734* conn -- PPPoE connection
735* msg -- printf-style format string
736* args -- arguments for msg
737*%RETURNS:
738* Nothing
739*%DESCRIPTION:
740* Sends a PADT packet with a formatted message
741***********************************************************************/
742void
743sendPADTf(PPPoEConnection *conn, char const *fmt, ...)
744{
745 char msg[512];
746 va_list ap;
747
748 va_start(ap, fmt);
749 vsnprintf(msg, sizeof(msg), fmt, ap);
750 va_end(ap);
751 msg[511] = 0;
752
753 sendPADT(conn, msg);
754}
755
756/**********************************************************************
757*%FUNCTION: pktLogErrs
758*%ARGUMENTS:
759* pkt -- packet type (a string)
760* type -- tag type
761* len -- tag length
762* data -- tag data
763* extra -- extra user data
764*%RETURNS:
765* Nothing
766*%DESCRIPTION:
767* Logs error tags
768***********************************************************************/
769void
770pktLogErrs(char const *pkt,
771 UINT16_t type, UINT16_t len, unsigned char *data,
772 void *extra)
773{
774 char const *str;
775 char const *fmt = "%s: %s: %.*s";
776 switch(type) {
777 case TAG_SERVICE_NAME_ERROR:
778 str = "Service-Name-Error";
779 break;
780 case TAG_AC_SYSTEM_ERROR:
781 str = "System-Error";
782 break;
783 default:
784 str = "Generic-Error";
785 }
786
787 syslog(LOG_ERR, fmt, pkt, str, (int) len, data);
788 fprintf(stderr, fmt, pkt, str, (int) len, data);
789 fprintf(stderr, "\n");
790}
791
792/**********************************************************************
793*%FUNCTION: parseLogErrs
794*%ARGUMENTS:
795* type -- tag type
796* len -- tag length
797* data -- tag data
798* extra -- extra user data
799*%RETURNS:
800* Nothing
801*%DESCRIPTION:
802* Picks error tags out of a packet and logs them.
803***********************************************************************/
804void
805parseLogErrs(UINT16_t type, UINT16_t len, unsigned char *data,
806 void *extra)
807{
808 pktLogErrs("PADT", type, len, data, extra);
809}
810