summaryrefslogtreecommitdiff
path: root/jni/src/common.c (plain)
blob: 63d5e584b272a118ef3bfc46d9ab8ce808d75f75
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 else if (len == 0) {
646 syslog(LOG_INFO, "sendSavedPADT: file(%s) is a empty file\n", padt_file);
647 fclose(file_fd);
648 unlink(padt_file);
649 return;
650 }
651
652 packet = malloc(len);
653 if (!packet){
654 syslog(LOG_INFO, "sendSavedPADT: failed to malloc");
655 goto free_file_fd;
656 }
657
658 fseek(file_fd, 0, SEEK_SET);
659 fread(packet, 1, len, file_fd);
660
661 fd = getRawSocket("eth0");
662 if ( fd < 0){
663 syslog(LOG_INFO, "sendSavedPADT: failed to getRawSocket");
664 goto free_packet;
665
666 }
667 send( fd, packet, len, 0);
668 syslog(LOG_INFO, "Send SavedPADT(fd = %d) by eth0", fd);
669
670 close(fd);
671
672free_packet:
673 free(packet);
674
675free_file_fd:
676 fclose(file_fd);
677}
678
679
680void
681savePADT(PPPoEConnection *conn, char const *msg)
682{
683 FILE *padt_file_bin = NULL;
684 PPPoEPacket packet;
685 unsigned char *cursor = packet.payload;
686
687 UINT16_t plen = 0;
688
689 memcpy(packet.ethHdr.h_dest, conn->peerEth, ETH_ALEN);
690 memcpy(packet.ethHdr.h_source, conn->myEth, ETH_ALEN);
691
692 packet.ethHdr.h_proto = htons(Eth_PPPOE_Discovery);
693 packet.ver = 1;
694 packet.type = 1;
695 packet.code = CODE_PADT;
696 packet.session = conn->session;
697
698 /* Reset Session to zero so there is no possibility of
699 recursive calls to this function by any signal handler */
700 //conn->session = 0;
701
702 /* If we're using Host-Uniq, copy it over */
703 if (conn->useHostUniq) {
704 PPPoETag hostUniq;
705 pid_t pid = getpid();
706 hostUniq.type = htons(TAG_HOST_UNIQ);
707 hostUniq.length = htons(sizeof(pid));
708 memcpy(hostUniq.payload, &pid, sizeof(pid));
709 memcpy(cursor, &hostUniq, sizeof(pid) + TAG_HDR_SIZE);
710 cursor += sizeof(pid) + TAG_HDR_SIZE;
711 plen += sizeof(pid) + TAG_HDR_SIZE;
712 }
713
714 /* Copy error message */
715 if (msg) {
716 PPPoETag err;
717 size_t elen = strlen(msg);
718 err.type = htons(TAG_GENERIC_ERROR);
719 err.length = htons(elen);
720 strcpy((char *) err.payload, msg);
721 memcpy(cursor, &err, elen + TAG_HDR_SIZE);
722 cursor += elen + TAG_HDR_SIZE;
723 plen += elen + TAG_HDR_SIZE;
724 }
725
726 packet.length = htons(plen);
727
728 padt_file_bin = fopen(_ROOT_PATH "/etc/ppp/padt_bin", "w");
729 if (!padt_file_bin) {
730 syslog(LOG_INFO,"failed to save padt_bin");
731 }
732 fwrite(&packet, (int) (plen + HDR_SIZE), 1, padt_file_bin);
733 fflush(padt_file_bin);
734 fclose(padt_file_bin);
735}
736
737/***********************************************************************
738*%FUNCTION: sendPADTf
739*%ARGUMENTS:
740* conn -- PPPoE connection
741* msg -- printf-style format string
742* args -- arguments for msg
743*%RETURNS:
744* Nothing
745*%DESCRIPTION:
746* Sends a PADT packet with a formatted message
747***********************************************************************/
748void
749sendPADTf(PPPoEConnection *conn, char const *fmt, ...)
750{
751 char msg[512];
752 va_list ap;
753
754 va_start(ap, fmt);
755 vsnprintf(msg, sizeof(msg), fmt, ap);
756 va_end(ap);
757 msg[511] = 0;
758
759 sendPADT(conn, msg);
760}
761
762/**********************************************************************
763*%FUNCTION: pktLogErrs
764*%ARGUMENTS:
765* pkt -- packet type (a string)
766* type -- tag type
767* len -- tag length
768* data -- tag data
769* extra -- extra user data
770*%RETURNS:
771* Nothing
772*%DESCRIPTION:
773* Logs error tags
774***********************************************************************/
775void
776pktLogErrs(char const *pkt,
777 UINT16_t type, UINT16_t len, unsigned char *data,
778 void *extra)
779{
780 char const *str;
781 char const *fmt = "%s: %s: %.*s";
782 switch(type) {
783 case TAG_SERVICE_NAME_ERROR:
784 str = "Service-Name-Error";
785 break;
786 case TAG_AC_SYSTEM_ERROR:
787 str = "System-Error";
788 break;
789 default:
790 str = "Generic-Error";
791 }
792
793 syslog(LOG_ERR, fmt, pkt, str, (int) len, data);
794 fprintf(stderr, fmt, pkt, str, (int) len, data);
795 fprintf(stderr, "\n");
796}
797
798/**********************************************************************
799*%FUNCTION: parseLogErrs
800*%ARGUMENTS:
801* type -- tag type
802* len -- tag length
803* data -- tag data
804* extra -- extra user data
805*%RETURNS:
806* Nothing
807*%DESCRIPTION:
808* Picks error tags out of a packet and logs them.
809***********************************************************************/
810void
811parseLogErrs(UINT16_t type, UINT16_t len, unsigned char *data,
812 void *extra)
813{
814 pktLogErrs("PADT", type, len, data, extra);
815}
816