ip.c revision 58034
1/* 2 * PPP IP Protocol Interface 3 * 4 * Written by Toshiharu OHNO (tony-o@iij.ad.jp) 5 * 6 * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd. 7 * 8 * Redistribution and use in source and binary forms are permitted 9 * provided that the above copyright notice and this paragraph are 10 * duplicated in all such forms and that any documentation, 11 * advertising materials, and other materials related to such 12 * distribution and use acknowledge that the software was developed 13 * by the Internet Initiative Japan. The name of the 14 * IIJ may not be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. 19 * 20 * $FreeBSD: head/usr.sbin/ppp/ip.c 58034 2000-03-14 01:46:54Z brian $ 21 * 22 * TODO: 23 * o Return ICMP message for filterd packet 24 * and optionaly record it into log. 25 */ 26#include <sys/param.h> 27#include <sys/socket.h> 28#include <netinet/in.h> 29#include <netinet/in_systm.h> 30#include <netinet/ip.h> 31#include <netinet/ip_icmp.h> 32#include <netinet/udp.h> 33#include <netinet/tcp.h> 34#include <arpa/inet.h> 35#include <sys/un.h> 36 37#include <errno.h> 38#include <stdio.h> 39#include <string.h> 40#include <termios.h> 41#include <unistd.h> 42 43#include "layer.h" 44#include "proto.h" 45#include "mbuf.h" 46#include "log.h" 47#include "defs.h" 48#include "timer.h" 49#include "fsm.h" 50#include "lqr.h" 51#include "hdlc.h" 52#include "throughput.h" 53#include "iplist.h" 54#include "slcompress.h" 55#include "ipcp.h" 56#include "filter.h" 57#include "descriptor.h" 58#include "lcp.h" 59#include "ccp.h" 60#include "link.h" 61#include "mp.h" 62#ifndef NORADIUS 63#include "radius.h" 64#endif 65#include "bundle.h" 66#include "tun.h" 67#include "ip.h" 68 69 70#define OPCODE_QUERY 0 71#define OPCODE_IQUERY 1 72#define OPCODE_STATUS 2 73 74struct dns_header { 75 u_short id; 76 unsigned qr : 1; 77 unsigned opcode : 4; 78 unsigned aa : 1; 79 unsigned tc : 1; 80 unsigned rd : 1; 81 unsigned ra : 1; 82 unsigned z : 3; 83 unsigned rcode : 4; 84 u_short qdcount; 85 u_short ancount; 86 u_short nscount; 87 u_short arcount; 88}; 89 90static const char * 91dns_Qclass2Txt(u_short qclass) 92{ 93 static char failure[6]; 94 struct { 95 u_short id; 96 const char *txt; 97 } qtxt[] = { 98 /* rfc1035 */ 99 { 1, "IN" }, { 2, "CS" }, { 3, "CH" }, { 4, "HS" }, { 255, "*" } 100 }; 101 int f; 102 103 for (f = 0; f < sizeof qtxt / sizeof *qtxt; f++) 104 if (qtxt[f].id == qclass) 105 return qtxt[f].txt; 106 107 return HexStr(qclass, failure, sizeof failure); 108} 109 110static const char * 111dns_Qtype2Txt(u_short qtype) 112{ 113 static char failure[6]; 114 struct { 115 u_short id; 116 const char *txt; 117 } qtxt[] = { 118 /* rfc1035/rfc1700 */ 119 { 1, "A" }, { 2, "NS" }, { 3, "MD" }, { 4, "MF" }, { 5, "CNAME" }, 120 { 6, "SOA" }, { 7, "MB" }, { 8, "MG" }, { 9, "MR" }, { 10, "NULL" }, 121 { 11, "WKS" }, { 12, "PTR" }, { 13, "HINFO" }, { 14, "MINFO" }, 122 { 15, "MX" }, { 16, "TXT" }, { 17, "RP" }, { 18, "AFSDB" }, 123 { 19, "X25" }, { 20, "ISDN" }, { 21, "RT" }, { 22, "NSAP" }, 124 { 23, "NSAP-PTR" }, { 24, "SIG" }, { 25, "KEY" }, { 26, "PX" }, 125 { 27, "GPOS" }, { 28, "AAAA" }, { 252, "AXFR" }, { 253, "MAILB" }, 126 { 254, "MAILA" }, { 255, "*" } 127 }; 128 int f; 129 130 for (f = 0; f < sizeof qtxt / sizeof *qtxt; f++) 131 if (qtxt[f].id == qtype) 132 return qtxt[f].txt; 133 134 return HexStr(qtype, failure, sizeof failure); 135} 136 137static __inline int 138PortMatch(int op, u_short pport, u_short rport) 139{ 140 switch (op) { 141 case OP_EQ: 142 return (pport == rport); 143 case OP_GT: 144 return (pport > rport); 145 case OP_LT: 146 return (pport < rport); 147 default: 148 return (0); 149 } 150} 151 152/* 153 * Check a packet against a defined filter 154 * Returns 0 to accept the packet, non-zero to drop the packet 155 * 156 * If filtering is enabled, the initial fragment of a datagram must 157 * contain the complete protocol header, and subsequent fragments 158 * must not attempt to over-write it. 159 */ 160static int 161FilterCheck(const struct ip *pip, const struct filter *filter) 162{ 163 int gotinfo; /* true if IP payload decoded */ 164 int cproto; /* P_* protocol type if (gotinfo) */ 165 int estab, syn, finrst; /* TCP state flags if (gotinfo) */ 166 u_short sport, dport; /* src, dest port from packet if (gotinfo) */ 167 int n; /* filter rule to process */ 168 int len; /* bytes used in dbuff */ 169 int didname; /* true if filter header printed */ 170 int match; /* true if condition matched */ 171 const struct filterent *fp = filter->rule; 172 char dbuff[100]; 173 174 if (fp->f_action == A_NONE) 175 return (0); /* No rule is given. Permit this packet */ 176 177 /* Deny any packet fragment that tries to over-write the header. 178 * Since we no longer have the real header available, punt on the 179 * largest normal header - 20 bytes for TCP without options, rounded 180 * up to the next possible fragment boundary. Since the smallest 181 * `legal' MTU is 576, and the smallest recommended MTU is 296, any 182 * fragmentation within this range is dubious at best */ 183 len = ntohs(pip->ip_off) & IP_OFFMASK; /* fragment offset */ 184 if (len > 0) { /* Not first fragment within datagram */ 185 if (len < (24 >> 3)) /* don't allow fragment to over-write header */ 186 return (1); 187 /* permit fragments on in and out filter */ 188 return (!filter->fragok); 189 } 190 191 cproto = gotinfo = estab = syn = finrst = didname = 0; 192 sport = dport = 0; 193 for (n = 0; n < MAXFILTERS; ) { 194 if (fp->f_action == A_NONE) { 195 n++; 196 fp++; 197 continue; 198 } 199 200 if (!didname) { 201 log_Printf(LogDEBUG, "%s filter:\n", filter->name); 202 didname = 1; 203 } 204 205 match = 0; 206 if (!((pip->ip_src.s_addr ^ fp->f_src.ipaddr.s_addr) & 207 fp->f_src.mask.s_addr) && 208 !((pip->ip_dst.s_addr ^ fp->f_dst.ipaddr.s_addr) & 209 fp->f_dst.mask.s_addr)) { 210 if (fp->f_proto != P_NONE) { 211 if (!gotinfo) { 212 const char *ptop = (const char *) pip + (pip->ip_hl << 2); 213 const struct tcphdr *th; 214 const struct udphdr *uh; 215 const struct icmp *ih; 216 int datalen; /* IP datagram length */ 217 218 datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2); 219 switch (pip->ip_p) { 220 case IPPROTO_ICMP: 221 cproto = P_ICMP; 222 if (datalen < 8) /* ICMP must be at least 8 octets */ 223 return (1); 224 ih = (const struct icmp *) ptop; 225 sport = ih->icmp_type; 226 estab = syn = finrst = -1; 227 if (log_IsKept(LogDEBUG)) 228 snprintf(dbuff, sizeof dbuff, "sport = %d", sport); 229 break; 230 case IPPROTO_IGMP: 231 cproto = P_IGMP; 232 if (datalen < 8) /* IGMP uses 8-octet messages */ 233 return (1); 234 estab = syn = finrst = -1; 235 sport = ntohs(0); 236 break; 237#ifdef IPPROTO_GRE 238 case IPPROTO_GRE: 239 cproto = P_GRE; 240 if (datalen < 2) /* GRE uses 2-octet+ messages */ 241 return (1); 242 estab = syn = finrst = -1; 243 sport = ntohs(0); 244 break; 245#endif 246#ifdef IPPROTO_OSPFIGP 247 case IPPROTO_OSPFIGP: 248 cproto = P_OSPF; 249 if (datalen < 8) /* IGMP uses 8-octet messages */ 250 return (1); 251 estab = syn = finrst = -1; 252 sport = ntohs(0); 253 break; 254#endif 255 case IPPROTO_UDP: 256 case IPPROTO_IPIP: 257 cproto = P_UDP; 258 if (datalen < 8) /* UDP header is 8 octets */ 259 return (1); 260 uh = (const struct udphdr *) ptop; 261 sport = ntohs(uh->uh_sport); 262 dport = ntohs(uh->uh_dport); 263 estab = syn = finrst = -1; 264 if (log_IsKept(LogDEBUG)) 265 snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d", 266 sport, dport); 267 break; 268 case IPPROTO_TCP: 269 cproto = P_TCP; 270 th = (const struct tcphdr *) ptop; 271 /* TCP headers are variable length. The following code 272 * ensures that the TCP header length isn't de-referenced if 273 * the datagram is too short 274 */ 275 if (datalen < 20 || datalen < (th->th_off << 2)) 276 return (1); 277 sport = ntohs(th->th_sport); 278 dport = ntohs(th->th_dport); 279 estab = (th->th_flags & TH_ACK); 280 syn = (th->th_flags & TH_SYN); 281 finrst = (th->th_flags & (TH_FIN|TH_RST)); 282 if (log_IsKept(LogDEBUG)) { 283 if (!estab) 284 snprintf(dbuff, sizeof dbuff, 285 "flags = %02x, sport = %d, dport = %d", 286 th->th_flags, sport, dport); 287 else 288 *dbuff = '\0'; 289 } 290 break; 291 default: 292 return (1); /* We'll block unknown type of packet */ 293 } 294 295 if (log_IsKept(LogDEBUG)) { 296 if (estab != -1) { 297 len = strlen(dbuff); 298 snprintf(dbuff + len, sizeof dbuff - len, 299 ", estab = %d, syn = %d, finrst = %d", 300 estab, syn, finrst); 301 } 302 log_Printf(LogDEBUG, " Filter: proto = %s, %s\n", 303 filter_Proto2Nam(cproto), dbuff); 304 } 305 gotinfo = 1; 306 } 307 if (log_IsKept(LogDEBUG)) { 308 if (fp->f_srcop != OP_NONE) { 309 snprintf(dbuff, sizeof dbuff, ", src %s %d", 310 filter_Op2Nam(fp->f_srcop), fp->f_srcport); 311 len = strlen(dbuff); 312 } else 313 len = 0; 314 if (fp->f_dstop != OP_NONE) { 315 snprintf(dbuff + len, sizeof dbuff - len, 316 ", dst %s %d", filter_Op2Nam(fp->f_dstop), 317 fp->f_dstport); 318 } else if (!len) 319 *dbuff = '\0'; 320 321 log_Printf(LogDEBUG, " rule = %d: Address match, " 322 "check against proto %s%s, action = %s\n", 323 n, filter_Proto2Nam(fp->f_proto), 324 dbuff, filter_Action2Nam(fp->f_action)); 325 } 326 327 if (cproto == fp->f_proto) { 328 if ((fp->f_srcop == OP_NONE || 329 PortMatch(fp->f_srcop, sport, fp->f_srcport)) && 330 (fp->f_dstop == OP_NONE || 331 PortMatch(fp->f_dstop, dport, fp->f_dstport)) && 332 (fp->f_estab == 0 || estab) && 333 (fp->f_syn == 0 || syn) && 334 (fp->f_finrst == 0 || finrst)) { 335 match = 1; 336 } 337 } 338 } else { 339 /* Address is matched and no protocol specified. Make a decision. */ 340 log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n, 341 filter_Action2Nam(fp->f_action)); 342 match = 1; 343 } 344 } else 345 log_Printf(LogDEBUG, " rule = %d: Address mismatch\n", n); 346 347 if (match != fp->f_invert) { 348 /* Take specified action */ 349 if (fp->f_action < A_NONE) 350 fp = &filter->rule[n = fp->f_action]; 351 else 352 return (fp->f_action != A_PERMIT); 353 } else { 354 n++; 355 fp++; 356 } 357 } 358 return (1); /* No rule is mached. Deny this packet */ 359} 360 361#ifdef notdef 362static void 363IcmpError(struct ip *pip, int code) 364{ 365 struct mbuf *bp; 366 367 if (pip->ip_p != IPPROTO_ICMP) { 368 bp = m_get(m_len, MB_IPIN); 369 memcpy(MBUF_CTOP(bp), ptr, m_len); 370 vj_SendFrame(bp); 371 ipcp_AddOutOctets(m_len); 372 } 373} 374#endif 375 376static void 377ip_LogDNS(const struct udphdr *uh, const char *direction) 378{ 379 struct dns_header header; 380 const u_short *pktptr; 381 const u_char *ptr; 382 u_short *hptr; 383 int len; 384 385 ptr = (const char *)uh + sizeof *uh; 386 len = ntohs(uh->uh_ulen) - sizeof *uh; 387 if (len < sizeof header + 5) /* rfc1024 */ 388 return; 389 390 pktptr = (const u_short *)ptr; 391 hptr = (u_short *)&header; 392 ptr += sizeof header; 393 len -= sizeof header; 394 395 while (pktptr < (const u_short *)ptr) { 396 *hptr++ = ntohs(*pktptr); /* Careful of macro side-effects ! */ 397 pktptr++; 398 } 399 400 if (header.opcode == OPCODE_QUERY && header.qr == 0) { 401 /* rfc1035 */ 402 char name[MAXHOSTNAMELEN + 1], *n; 403 const char *qtype, *qclass; 404 const u_char *end; 405 406 n = name; 407 end = ptr + len - 4; 408 if (end - ptr > MAXHOSTNAMELEN) 409 end = ptr + MAXHOSTNAMELEN; 410 while (ptr < end) { 411 len = *ptr++; 412 if (len > end - ptr) 413 len = end - ptr; 414 if (n != name) 415 *n++ = '.'; 416 memcpy(n, ptr, len); 417 ptr += len; 418 n += len; 419 } 420 *n = '\0'; 421 qtype = dns_Qtype2Txt(ntohs(*(const u_short *)end)); 422 qclass = dns_Qclass2Txt(ntohs(*(const u_short *)(end + 2))); 423 424 log_Printf(LogDNS, "%sbound query %s %s %s\n", 425 direction, qclass, qtype, name); 426 } 427} 428 429/* 430 * For debugging aid. 431 */ 432int 433PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter) 434{ 435 static const char *const TcpFlags[] = { 436 "FIN", "SYN", "RST", "PSH", "ACK", "URG" 437 }; 438 struct ip *pip; 439 struct tcphdr *th; 440 struct udphdr *uh; 441 struct icmp *icmph; 442 char *ptop; 443 int mask, len, n, pri, logit, loglen, result; 444 char logbuf[200]; 445 446 logit = (log_IsKept(LogTCPIP) || log_IsKept(LogDNS)) && filter->logok; 447 loglen = 0; 448 pri = 0; 449 450 pip = (struct ip *)cp; 451 uh = NULL; 452 453 if (logit && loglen < sizeof logbuf) { 454 snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name); 455 loglen += strlen(logbuf + loglen); 456 } 457 ptop = (cp + (pip->ip_hl << 2)); 458 459 switch (pip->ip_p) { 460 case IPPROTO_ICMP: 461 if (logit && loglen < sizeof logbuf) { 462 icmph = (struct icmp *) ptop; 463 snprintf(logbuf + loglen, sizeof logbuf - loglen, 464 "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type); 465 loglen += strlen(logbuf + loglen); 466 snprintf(logbuf + loglen, sizeof logbuf - loglen, 467 "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type); 468 loglen += strlen(logbuf + loglen); 469 } 470 break; 471 472 case IPPROTO_UDP: 473 uh = (struct udphdr *) ptop; 474 if (pip->ip_tos == IPTOS_LOWDELAY) 475 pri++; 476 477 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0 && 478 ipcp_IsUrgentUdpPort(&bundle->ncp.ipcp, ntohs(uh->uh_sport), 479 ntohs(uh->uh_dport))) 480 pri++; 481 482 if (logit && loglen < sizeof logbuf) { 483 snprintf(logbuf + loglen, sizeof logbuf - loglen, 484 "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 485 loglen += strlen(logbuf + loglen); 486 snprintf(logbuf + loglen, sizeof logbuf - loglen, 487 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 488 loglen += strlen(logbuf + loglen); 489 } 490 break; 491 492#ifdef IPPROTO_GRE 493 case IPPROTO_GRE: 494 if (logit && loglen < sizeof logbuf) { 495 snprintf(logbuf + loglen, sizeof logbuf - loglen, 496 "GRE: %s ---> ", inet_ntoa(pip->ip_src)); 497 loglen += strlen(logbuf + loglen); 498 snprintf(logbuf + loglen, sizeof logbuf - loglen, 499 "%s", inet_ntoa(pip->ip_dst)); 500 loglen += strlen(logbuf + loglen); 501 } 502 break; 503#endif 504 505#ifdef IPPROTO_OSPFIGP 506 case IPPROTO_OSPFIGP: 507 if (logit && loglen < sizeof logbuf) { 508 snprintf(logbuf + loglen, sizeof logbuf - loglen, 509 "OSPF: %s ---> ", inet_ntoa(pip->ip_src)); 510 loglen += strlen(logbuf + loglen); 511 snprintf(logbuf + loglen, sizeof logbuf - loglen, 512 "%s", inet_ntoa(pip->ip_dst)); 513 loglen += strlen(logbuf + loglen); 514 } 515 break; 516#endif 517 518 case IPPROTO_IPIP: 519 if (logit && loglen < sizeof logbuf) { 520 uh = (struct udphdr *) ptop; 521 snprintf(logbuf + loglen, sizeof logbuf - loglen, 522 "IPIP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 523 loglen += strlen(logbuf + loglen); 524 snprintf(logbuf + loglen, sizeof logbuf - loglen, 525 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 526 loglen += strlen(logbuf + loglen); 527 } 528 break; 529 530 case IPPROTO_IGMP: 531 if (logit && loglen < sizeof logbuf) { 532 uh = (struct udphdr *) ptop; 533 snprintf(logbuf + loglen, sizeof logbuf - loglen, 534 "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 535 loglen += strlen(logbuf + loglen); 536 snprintf(logbuf + loglen, sizeof logbuf - loglen, 537 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 538 loglen += strlen(logbuf + loglen); 539 } 540 break; 541 542 case IPPROTO_TCP: 543 th = (struct tcphdr *) ptop; 544 if (pip->ip_tos == IPTOS_LOWDELAY) 545 pri++; 546 547 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0 && 548 ipcp_IsUrgentTcpPort(&bundle->ncp.ipcp, ntohs(th->th_sport), 549 ntohs(th->th_dport))) 550 pri++; 551 552 if (logit && loglen < sizeof logbuf) { 553 len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2); 554 snprintf(logbuf + loglen, sizeof logbuf - loglen, 555 "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport)); 556 loglen += strlen(logbuf + loglen); 557 snprintf(logbuf + loglen, sizeof logbuf - loglen, 558 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport)); 559 loglen += strlen(logbuf + loglen); 560 n = 0; 561 for (mask = TH_FIN; mask != 0x40; mask <<= 1) { 562 if (th->th_flags & mask) { 563 snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]); 564 loglen += strlen(logbuf + loglen); 565 } 566 n++; 567 } 568 snprintf(logbuf + loglen, sizeof logbuf - loglen, 569 " seq:%lx ack:%lx (%d/%d)", 570 (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb); 571 loglen += strlen(logbuf + loglen); 572 if ((th->th_flags & TH_SYN) && nb > 40) { 573 u_short *sp; 574 575 ptop += 20; 576 sp = (u_short *) ptop; 577 if (ntohs(sp[0]) == 0x0204) { 578 snprintf(logbuf + loglen, sizeof logbuf - loglen, 579 " MSS = %d", ntohs(sp[1])); 580 loglen += strlen(logbuf + loglen); 581 } 582 } 583 } 584 break; 585 } 586 587 if (FilterCheck(pip, filter)) { 588 if (logit) 589 log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf); 590#ifdef notdef 591 if (direction == 0) 592 IcmpError(pip, pri); 593#endif 594 result = -1; 595 } else { 596 /* Check Keep Alive filter */ 597 if (logit && log_IsKept(LogTCPIP)) { 598 if (FilterCheck(pip, &bundle->filter.alive)) 599 log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf); 600 else 601 log_Printf(LogTCPIP, "%s\n", logbuf); 602 } 603 result = pri; 604 } 605 606 if (uh && ntohs(uh->uh_dport) == 53 && log_IsKept(LogDNS)) 607 ip_LogDNS(uh, filter->name); 608 609 return result; 610} 611 612struct mbuf * 613ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp) 614{ 615 int nb, nw; 616 struct tun_data tun; 617 struct ip *pip; 618 char *data; 619 620 if (bundle->ncp.ipcp.fsm.state != ST_OPENED) { 621 log_Printf(LogWARN, "ip_Input: IPCP not open - packet dropped\n"); 622 m_freem(bp); 623 return NULL; 624 } 625 626 m_settype(bp, MB_IPIN); 627 nb = m_length(bp); 628 if (nb > sizeof tun.data) { 629 log_Printf(LogWARN, "ip_Input: %s: Packet too large (got %d, max %d)\n", 630 l->name, nb, (int)(sizeof tun.data)); 631 m_freem(bp); 632 return NULL; 633 } 634 mbuf_Read(bp, tun.data, nb); 635 636 if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) 637 return NULL; 638 639 pip = (struct ip *)tun.data; 640 if (!FilterCheck(pip, &bundle->filter.alive)) 641 bundle_StartIdleTimer(bundle); 642 643 ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 644 645 if (bundle->dev.header) { 646 tun.family = htonl(AF_INET); 647 nb += sizeof tun - sizeof tun.data; 648 data = (char *)&tun; 649 } else 650 data = tun.data; 651 652 nw = write(bundle->dev.fd, data, nb); 653 if (nw != nb) { 654 if (nw == -1) 655 log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %s\n", 656 l->name, nb, strerror(errno)); 657 else 658 log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %d\n", l->name, nb, nw); 659 } 660 661 return NULL; 662} 663 664void 665ip_Enqueue(struct ipcp *ipcp, int pri, char *ptr, int count) 666{ 667 struct mbuf *bp; 668 669 if (pri < 0 || pri >= IPCP_QUEUES(ipcp)) 670 log_Printf(LogERROR, "Can't store in ip queue %d\n", pri); 671 else { 672 /* 673 * We allocate an extra 6 bytes, four at the front and two at the end. 674 * This is an optimisation so that we need to do less work in 675 * m_prepend() in acf_LayerPush() and proto_LayerPush() and 676 * appending in hdlc_LayerPush(). 677 */ 678 bp = m_get(count + 6, MB_IPOUT); 679 bp->m_offset += 4; 680 bp->m_len -= 6; 681 memcpy(MBUF_CTOP(bp), ptr, count); 682 m_enqueue(ipcp->Queue + pri, bp); 683 } 684} 685 686void 687ip_DeleteQueue(struct ipcp *ipcp) 688{ 689 struct mqueue *queue; 690 691 for (queue = ipcp->Queue; queue < ipcp->Queue + IPCP_QUEUES(ipcp); queue++) 692 while (queue->top) 693 m_freem(m_dequeue(queue)); 694} 695 696size_t 697ip_QueueLen(struct ipcp *ipcp) 698{ 699 struct mqueue *queue; 700 size_t result; 701 702 result = 0; 703 for (queue = ipcp->Queue; queue < ipcp->Queue + IPCP_QUEUES(ipcp); queue++) 704 result += queue->len; 705 706 return result; 707} 708 709int 710ip_PushPacket(struct link *l, struct bundle *bundle) 711{ 712 struct ipcp *ipcp = &bundle->ncp.ipcp; 713 struct mqueue *queue; 714 struct mbuf *bp; 715 struct ip *pip; 716 int m_len; 717 718 if (ipcp->fsm.state != ST_OPENED) 719 return 0; 720 721 queue = ipcp->Queue + IPCP_QUEUES(ipcp) - 1; 722 do { 723 if (queue->top) { 724 bp = m_pullup(m_dequeue(queue)); 725 m_len = m_length(bp); 726 pip = (struct ip *)MBUF_CTOP(bp); 727 if (!FilterCheck(pip, &bundle->filter.alive)) 728 bundle_StartIdleTimer(bundle); 729 link_PushPacket(l, bp, bundle, 0, PROTO_IP); 730 ipcp_AddOutOctets(ipcp, m_len); 731 return 1; 732 } 733 } while (queue-- != ipcp->Queue); 734 735 return 0; 736} 737