ip.c revision 45103
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 * $Id: ip.c,v 1.55 1999/01/28 01:56:32 brian Exp $ 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#ifdef __OpenBSD__ 28#include <sys/socket.h> 29#endif 30#include <netinet/in.h> 31#include <netinet/in_systm.h> 32#include <netinet/ip.h> 33#include <netinet/ip_icmp.h> 34#include <netinet/udp.h> 35#include <netinet/tcp.h> 36#include <arpa/inet.h> 37#include <sys/un.h> 38 39#include <errno.h> 40#include <stdio.h> 41#include <stdlib.h> 42#include <string.h> 43#include <unistd.h> 44 45#ifndef NOALIAS 46#ifdef __OpenBSD__ 47#include "alias.h" 48#else 49#include <alias.h> 50#endif 51#endif 52#include "mbuf.h" 53#include "log.h" 54#include "defs.h" 55#include "timer.h" 56#include "fsm.h" 57#include "lqr.h" 58#include "hdlc.h" 59#include "throughput.h" 60#include "iplist.h" 61#include "slcompress.h" 62#include "ipcp.h" 63#include "filter.h" 64#include "descriptor.h" 65#include "lcp.h" 66#include "ccp.h" 67#include "link.h" 68#include "mp.h" 69#ifndef NORADIUS 70#include "radius.h" 71#endif 72#include "bundle.h" 73#include "vjcomp.h" 74#include "tun.h" 75#include "ip.h" 76 77static const u_short interactive_ports[32] = { 78 544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 79 0, 0, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543, 80}; 81 82#define INTERACTIVE(p) (interactive_ports[(p) & 0x1F] == (p)) 83 84static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" }; 85 86static int 87PortMatch(int op, u_short pport, u_short rport) 88{ 89 switch (op) { 90 case OP_EQ: 91 return (pport == rport); 92 case OP_GT: 93 return (pport > rport); 94 case OP_LT: 95 return (pport < rport); 96 default: 97 return (0); 98 } 99} 100 101/* 102 * Check a packet against with defined filters 103 */ 104static int 105FilterCheck(struct ip *pip, struct filter *filter) 106{ 107 int gotinfo, cproto, estab, syn, finrst, n, len, didname; 108 struct tcphdr *th; 109 struct udphdr *uh; 110 struct icmp *ih; 111 char *ptop; 112 u_short sport, dport; 113 struct filterent *fp = filter->rule; 114 char dbuff[100]; 115 116 if (fp->action) { 117 cproto = gotinfo = estab = syn = finrst = didname = 0; 118 sport = dport = 0; 119 for (n = 0; n < MAXFILTERS; n++) { 120 if (fp->action) { 121 /* permit fragments on in and out filter */ 122 if (filter->fragok && (ntohs(pip->ip_off) & IP_OFFMASK) != 0) 123 return (A_PERMIT); 124 125 if (!didname) 126 log_Printf(LogDEBUG, "%s filter:\n", filter->name); 127 didname = 1; 128 129 if ((pip->ip_src.s_addr & fp->smask.s_addr) == 130 (fp->saddr.s_addr & fp->smask.s_addr) && 131 (pip->ip_dst.s_addr & fp->dmask.s_addr) == 132 (fp->daddr.s_addr & fp->dmask.s_addr)) { 133 if (fp->proto) { 134 if (!gotinfo) { 135 ptop = (char *) pip + (pip->ip_hl << 2); 136 137 switch (pip->ip_p) { 138 case IPPROTO_ICMP: 139 cproto = P_ICMP; 140 ih = (struct icmp *) ptop; 141 sport = ih->icmp_type; 142 estab = syn = finrst = -1; 143 if (log_IsKept(LogDEBUG)) 144 snprintf(dbuff, sizeof dbuff, "sport = %d", sport); 145 break; 146 case IPPROTO_UDP: 147 case IPPROTO_IGMP: 148 case IPPROTO_IPIP: 149 cproto = P_UDP; 150 uh = (struct udphdr *) ptop; 151 sport = ntohs(uh->uh_sport); 152 dport = ntohs(uh->uh_dport); 153 estab = syn = finrst = -1; 154 if (log_IsKept(LogDEBUG)) 155 snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d", 156 sport, dport); 157 break; 158 case IPPROTO_TCP: 159 cproto = P_TCP; 160 th = (struct tcphdr *) ptop; 161 sport = ntohs(th->th_sport); 162 dport = ntohs(th->th_dport); 163 estab = (th->th_flags & TH_ACK); 164 syn = (th->th_flags & TH_SYN); 165 finrst = (th->th_flags & (TH_FIN|TH_RST)); 166 if (log_IsKept(LogDEBUG)) { 167 if (!estab) 168 snprintf(dbuff, sizeof dbuff, 169 "flags = %02x, sport = %d, dport = %d", 170 th->th_flags, sport, dport); 171 else 172 *dbuff = '\0'; 173 } 174 break; 175 default: 176 return (A_DENY); /* We'll block unknown type of packet */ 177 } 178 if (log_IsKept(LogDEBUG)) { 179 if (estab != -1) { 180 len = strlen(dbuff); 181 snprintf(dbuff + len, sizeof dbuff - len, 182 ", estab = %d, syn = %d, finrst = %d", 183 estab, syn, finrst); 184 } 185 log_Printf(LogDEBUG, " Filter: proto = %s, %s\n", 186 filter_Proto2Nam(cproto), dbuff); 187 } 188 gotinfo = 1; 189 } 190 if (log_IsKept(LogDEBUG)) { 191 if (fp->opt.srcop != OP_NONE) { 192 snprintf(dbuff, sizeof dbuff, ", src %s %d", 193 filter_Op2Nam(fp->opt.srcop), fp->opt.srcport); 194 len = strlen(dbuff); 195 } else 196 len = 0; 197 if (fp->opt.dstop != OP_NONE) { 198 snprintf(dbuff + len, sizeof dbuff - len, 199 ", dst %s %d", filter_Op2Nam(fp->opt.dstop), 200 fp->opt.dstport); 201 } else if (!len) 202 *dbuff = '\0'; 203 204 log_Printf(LogDEBUG, " rule = %d: Address match, " 205 "check against proto %s%s, action = %s\n", 206 n, filter_Proto2Nam(fp->proto), 207 dbuff, filter_Action2Nam(fp->action)); 208 } 209 210 if (cproto == fp->proto) { 211 if ((fp->opt.srcop == OP_NONE || 212 PortMatch(fp->opt.srcop, sport, fp->opt.srcport)) && 213 (fp->opt.dstop == OP_NONE || 214 PortMatch(fp->opt.dstop, dport, fp->opt.dstport)) && 215 (fp->opt.estab == 0 || estab) && 216 (fp->opt.syn == 0 || syn) && 217 (fp->opt.finrst == 0 || finrst)) { 218 return (fp->action); 219 } 220 } 221 } else { 222 /* Address is mached. Make a decision. */ 223 log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n, 224 filter_Action2Nam(fp->action)); 225 return (fp->action); 226 } 227 } else 228 log_Printf(LogDEBUG, " rule = %d: Address mismatch\n", n); 229 } 230 fp++; 231 } 232 return (A_DENY); /* No rule is mached. Deny this packet */ 233 } 234 return (A_PERMIT); /* No rule is given. Permit this packet */ 235} 236 237#ifdef notdef 238static void 239IcmpError(struct ip * pip, int code) 240{ 241 struct mbuf *bp; 242 243 if (pip->ip_p != IPPROTO_ICMP) { 244 bp = mbuf_Alloc(cnt, MB_IPIN); 245 memcpy(MBUF_CTOP(bp), ptr, cnt); 246 vj_SendFrame(bp); 247 ipcp_AddOutOctets(cnt); 248 } 249} 250#endif 251 252/* 253 * For debugging aid. 254 */ 255int 256PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter) 257{ 258 struct ip *pip; 259 struct tcphdr *th; 260 struct udphdr *uh; 261 struct icmp *icmph; 262 char *ptop; 263 int mask, len, n; 264 int pri = PRI_NORMAL; 265 int logit, loglen; 266 char logbuf[200]; 267 268 logit = log_IsKept(LogTCPIP) && filter->logok; 269 loglen = 0; 270 271 pip = (struct ip *) cp; 272 273 if (logit && loglen < sizeof logbuf) { 274 snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name); 275 loglen += strlen(logbuf + loglen); 276 } 277 ptop = (cp + (pip->ip_hl << 2)); 278 279 switch (pip->ip_p) { 280 case IPPROTO_ICMP: 281 if (logit && loglen < sizeof logbuf) { 282 icmph = (struct icmp *) ptop; 283 snprintf(logbuf + loglen, sizeof logbuf - loglen, 284 "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type); 285 loglen += strlen(logbuf + loglen); 286 snprintf(logbuf + loglen, sizeof logbuf - loglen, 287 "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type); 288 loglen += strlen(logbuf + loglen); 289 } 290 break; 291 case IPPROTO_UDP: 292 if (logit && loglen < sizeof logbuf) { 293 uh = (struct udphdr *) ptop; 294 snprintf(logbuf + loglen, sizeof logbuf - loglen, 295 "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 296 loglen += strlen(logbuf + loglen); 297 snprintf(logbuf + loglen, sizeof logbuf - loglen, 298 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 299 loglen += strlen(logbuf + loglen); 300 } 301 break; 302 case IPPROTO_IPIP: 303 if (logit && loglen < sizeof logbuf) { 304 uh = (struct udphdr *) ptop; 305 snprintf(logbuf + loglen, sizeof logbuf - loglen, 306 "IPIP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 307 loglen += strlen(logbuf + loglen); 308 snprintf(logbuf + loglen, sizeof logbuf - loglen, 309 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 310 loglen += strlen(logbuf + loglen); 311 } 312 break; 313 case IPPROTO_IGMP: 314 if (logit && loglen < sizeof logbuf) { 315 uh = (struct udphdr *) ptop; 316 snprintf(logbuf + loglen, sizeof logbuf - loglen, 317 "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport)); 318 loglen += strlen(logbuf + loglen); 319 snprintf(logbuf + loglen, sizeof logbuf - loglen, 320 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport)); 321 loglen += strlen(logbuf + loglen); 322 } 323 break; 324 case IPPROTO_TCP: 325 th = (struct tcphdr *) ptop; 326 if (pip->ip_tos == IPTOS_LOWDELAY) 327 pri = PRI_FAST; 328 else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { 329 if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport))) 330 pri = PRI_FAST; 331 } 332 if (logit && loglen < sizeof logbuf) { 333 len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2); 334 snprintf(logbuf + loglen, sizeof logbuf - loglen, 335 "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport)); 336 loglen += strlen(logbuf + loglen); 337 snprintf(logbuf + loglen, sizeof logbuf - loglen, 338 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport)); 339 loglen += strlen(logbuf + loglen); 340 n = 0; 341 for (mask = TH_FIN; mask != 0x40; mask <<= 1) { 342 if (th->th_flags & mask) { 343 snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]); 344 loglen += strlen(logbuf + loglen); 345 } 346 n++; 347 } 348 snprintf(logbuf + loglen, sizeof logbuf - loglen, 349 " seq:%lx ack:%lx (%d/%d)", 350 (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb); 351 loglen += strlen(logbuf + loglen); 352 if ((th->th_flags & TH_SYN) && nb > 40) { 353 u_short *sp; 354 355 ptop += 20; 356 sp = (u_short *) ptop; 357 if (ntohs(sp[0]) == 0x0204) { 358 snprintf(logbuf + loglen, sizeof logbuf - loglen, 359 " MSS = %d", ntohs(sp[1])); 360 loglen += strlen(logbuf + loglen); 361 } 362 } 363 } 364 break; 365 } 366 367 if ((FilterCheck(pip, filter) & A_DENY)) { 368 if (logit) 369 log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf); 370#ifdef notdef 371 if (direction == 0) 372 IcmpError(pip, pri); 373#endif 374 return (-1); 375 } else { 376 /* Check Keep Alive filter */ 377 if (logit) { 378 if (FilterCheck(pip, &bundle->filter.alive) & A_DENY) 379 log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf); 380 else 381 log_Printf(LogTCPIP, "%s\n", logbuf); 382 } 383 return (pri); 384 } 385} 386 387void 388ip_Input(struct bundle *bundle, struct mbuf * bp) 389{ 390 u_char *cp; 391 struct mbuf *wp; 392 int nb, nw; 393 struct tun_data tun; 394 struct ip *pip = (struct ip *)tun.data; 395#ifndef NOALIAS 396 struct ip *piip = (struct ip *)((char *)pip + (pip->ip_hl << 2)); 397#endif 398 399 tun_fill_header(tun, AF_INET); 400 cp = tun.data; 401 nb = 0; 402 for (wp = bp; wp; wp = wp->next) { /* Copy to contiguous region */ 403 if (sizeof tun.data - (cp - tun.data) < wp->cnt) { 404 log_Printf(LogWARN, "ip_Input: Packet too large (%d) - dropped\n", 405 mbuf_Length(bp)); 406 mbuf_Free(bp); 407 return; 408 } 409 memcpy(cp, MBUF_CTOP(wp), wp->cnt); 410 cp += wp->cnt; 411 nb += wp->cnt; 412 } 413 414#ifndef NOALIAS 415 if (bundle->AliasEnabled && pip->ip_p != IPPROTO_IGMP && 416 (pip->ip_p != IPPROTO_IPIP || !IN_CLASSD(ntohl(piip->ip_dst.s_addr)))) { 417 struct tun_data *frag; 418 int iresult; 419 char *fptr; 420 421 iresult = PacketAliasIn(tun.data, sizeof tun.data); 422 nb = ntohs(((struct ip *) tun.data)->ip_len); 423 424 if (nb > MAX_MRU) { 425 log_Printf(LogWARN, "ip_Input: Problem with IP header length\n"); 426 mbuf_Free(bp); 427 return; 428 } 429 if (iresult == PKT_ALIAS_OK 430 || iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) { 431 if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) { 432 mbuf_Free(bp); 433 return; 434 } 435 436 if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY)) 437 bundle_StartIdleTimer(bundle); 438 439 ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 440 441 nb = ntohs(((struct ip *) tun.data)->ip_len); 442 nb += sizeof tun - sizeof tun.data; 443 nw = write(bundle->dev.fd, &tun, nb); 444 if (nw != nb) { 445 if (nw == -1) 446 log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb, 447 strerror(errno)); 448 else 449 log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw); 450 } 451 452 if (iresult == PKT_ALIAS_FOUND_HEADER_FRAGMENT) { 453 while ((fptr = PacketAliasGetFragment(tun.data)) != NULL) { 454 PacketAliasFragmentIn(tun.data, fptr); 455 nb = ntohs(((struct ip *) fptr)->ip_len); 456 frag = (struct tun_data *) 457 ((char *)fptr - sizeof tun + sizeof tun.data); 458 nb += sizeof tun - sizeof tun.data; 459 nw = write(bundle->dev.fd, frag, nb); 460 if (nw != nb) { 461 if (nw == -1) 462 log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb, 463 strerror(errno)); 464 else 465 log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw); 466 } 467 free(frag); 468 } 469 } 470 } else if (iresult == PKT_ALIAS_UNRESOLVED_FRAGMENT) { 471 nb = ntohs(((struct ip *) tun.data)->ip_len); 472 nb += sizeof tun - sizeof tun.data; 473 frag = (struct tun_data *)malloc(nb); 474 if (frag == NULL) 475 log_Printf(LogALERT, "ip_Input: Cannot allocate memory for fragment\n"); 476 else { 477 tun_fill_header(*frag, AF_INET); 478 memcpy(frag->data, tun.data, nb - sizeof tun + sizeof tun.data); 479 PacketAliasSaveFragment(frag->data); 480 } 481 } 482 } else 483#endif /* #ifndef NOALIAS */ 484 { /* no aliasing */ 485 if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0) { 486 mbuf_Free(bp); 487 return; 488 } 489 490 if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY)) 491 bundle_StartIdleTimer(bundle); 492 493 ipcp_AddInOctets(&bundle->ncp.ipcp, nb); 494 495 nb += sizeof tun - sizeof tun.data; 496 nw = write(bundle->dev.fd, &tun, nb); 497 if (nw != nb) { 498 if (nw == -1) 499 log_Printf(LogERROR, "ip_Input: wrote %d, got %s\n", nb, strerror(errno)); 500 else 501 log_Printf(LogERROR, "ip_Input: wrote %d, got %d\n", nb, nw); 502 } 503 } 504 mbuf_Free(bp); 505} 506 507void 508ip_Enqueue(struct ipcp *ipcp, int pri, char *ptr, int count) 509{ 510 struct mbuf *bp; 511 512 if (pri < 0 || pri > sizeof ipcp->Queue / sizeof ipcp->Queue[0]) 513 log_Printf(LogERROR, "Can't store in ip queue %d\n", pri); 514 else { 515 bp = mbuf_Alloc(count, MB_IPQ); 516 memcpy(MBUF_CTOP(bp), ptr, count); 517 mbuf_Enqueue(&ipcp->Queue[pri], bp); 518 } 519} 520 521void 522ip_DeleteQueue(struct ipcp *ipcp) 523{ 524 struct mqueue *queue; 525 526 for (queue = ipcp->Queue; queue < ipcp->Queue + PRI_MAX; queue++) 527 while (queue->top) 528 mbuf_Free(mbuf_Dequeue(queue)); 529} 530 531int 532ip_QueueLen(struct ipcp *ipcp) 533{ 534 struct mqueue *queue; 535 int result = 0; 536 537 for (queue = ipcp->Queue; queue < ipcp->Queue + PRI_MAX; queue++) 538 result += queue->qlen; 539 540 return result; 541} 542 543int 544ip_FlushPacket(struct link *l, struct bundle *bundle) 545{ 546 struct ipcp *ipcp = &bundle->ncp.ipcp; 547 struct mqueue *queue; 548 struct mbuf *bp; 549 int cnt; 550 551 if (ipcp->fsm.state != ST_OPENED) 552 return 0; 553 554 for (queue = &ipcp->Queue[PRI_FAST]; queue >= ipcp->Queue; queue--) 555 if (queue->top) { 556 bp = mbuf_Contiguous(mbuf_Dequeue(queue)); 557 if (bp) { 558 struct ip *pip = (struct ip *)MBUF_CTOP(bp); 559 560 cnt = mbuf_Length(bp); 561 if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY)) 562 bundle_StartIdleTimer(bundle); 563 vj_SendFrame(l, bp, bundle); 564 ipcp_AddOutOctets(ipcp, cnt); 565 return 1; 566 } 567 } 568 569 return 0; 570} 571