2 * PPP IP Protocol Interface
4 * Written by Toshiharu OHNO (tony-o@iij.ad.jp)
6 * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
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.
23 * o Return ICMP message for filterd packet
24 * and optionaly record it into log.
26 #include <sys/param.h>
27 #if defined(__OpenBSD__) || defined(__NetBSD__)
28 #include <sys/socket.h>
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>
54 #include "throughput.h"
56 #include "slcompress.h"
59 #include "descriptor.h"
71 static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" };
74 PortMatch(int op, u_short pport, u_short rport)
78 return (pport == rport);
80 return (pport > rport);
82 return (pport < rport);
89 * Check a packet against a defined filter
90 * Returns 0 to accept the packet, non-zero to drop the packet
92 * If filtering is enabled, the initial fragment of a datagram must
93 * contain the complete protocol header, and subsequent fragments
94 * must not attempt to over-write it.
97 FilterCheck(const struct ip *pip, const struct filter *filter)
99 int gotinfo; /* true if IP payload decoded */
100 int cproto; /* P_* protocol type if (gotinfo) */
101 int estab, syn, finrst; /* TCP state flags if (gotinfo) */
102 u_short sport, dport; /* src, dest port from packet if (gotinfo) */
103 int n; /* filter rule to process */
104 int len; /* bytes used in dbuff */
105 int didname; /* true if filter header printed */
106 int match; /* true if condition matched */
107 const struct filterent *fp = filter->rule;
110 if (fp->f_action == A_NONE)
111 return (0); /* No rule is given. Permit this packet */
113 /* Deny any packet fragment that tries to over-write the header.
114 * Since we no longer have the real header available, punt on the
115 * largest normal header - 20 bytes for TCP without options, rounded
116 * up to the next possible fragment boundary. Since the smallest
117 * `legal' MTU is 576, and the smallest recommended MTU is 296, any
118 * fragmentation within this range is dubious at best */
119 len = ntohs(pip->ip_off) & IP_OFFMASK; /* fragment offset */
120 if (len > 0) { /* Not first fragment within datagram */
121 if (len < (24 >> 3)) /* don't allow fragment to over-write header */
123 /* permit fragments on in and out filter */
124 return (!filter->fragok);
127 cproto = gotinfo = estab = syn = finrst = didname = 0;
129 for (n = 0; n < MAXFILTERS; ) {
130 if (fp->f_action == A_NONE) {
137 log_Printf(LogDEBUG, "%s filter:\n", filter->name);
142 if (!((pip->ip_src.s_addr ^ fp->f_src.ipaddr.s_addr) &
143 fp->f_src.mask.s_addr) &&
144 !((pip->ip_dst.s_addr ^ fp->f_dst.ipaddr.s_addr) &
145 fp->f_dst.mask.s_addr)) {
146 if (fp->f_proto != P_NONE) {
148 const char *ptop = (const char *) pip + (pip->ip_hl << 2);
149 const struct tcphdr *th;
150 const struct udphdr *uh;
151 const struct icmp *ih;
152 int datalen; /* IP datagram length */
154 datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
158 if (datalen < 8) /* ICMP must be at least 8 octets */
160 ih = (const struct icmp *) ptop;
161 sport = ih->icmp_type;
162 estab = syn = finrst = -1;
163 if (log_IsKept(LogDEBUG))
164 snprintf(dbuff, sizeof dbuff, "sport = %d", sport);
168 if (datalen < 8) /* IGMP uses 8-octet messages */
170 estab = syn = finrst = -1;
176 if (datalen < 2) /* GRE uses 2-octet+ messages */
178 estab = syn = finrst = -1;
182 #ifdef IPPROTO_OSPFIGP
183 case IPPROTO_OSPFIGP:
185 if (datalen < 8) /* IGMP uses 8-octet messages */
187 estab = syn = finrst = -1;
194 if (datalen < 8) /* UDP header is 8 octets */
196 uh = (const struct udphdr *) ptop;
197 sport = ntohs(uh->uh_sport);
198 dport = ntohs(uh->uh_dport);
199 estab = syn = finrst = -1;
200 if (log_IsKept(LogDEBUG))
201 snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d",
206 th = (const struct tcphdr *) ptop;
207 /* TCP headers are variable length. The following code
208 * ensures that the TCP header length isn't de-referenced if
209 * the datagram is too short
211 if (datalen < 20 || datalen < (th->th_off << 2))
213 sport = ntohs(th->th_sport);
214 dport = ntohs(th->th_dport);
215 estab = (th->th_flags & TH_ACK);
216 syn = (th->th_flags & TH_SYN);
217 finrst = (th->th_flags & (TH_FIN|TH_RST));
218 if (log_IsKept(LogDEBUG)) {
220 snprintf(dbuff, sizeof dbuff,
221 "flags = %02x, sport = %d, dport = %d",
222 th->th_flags, sport, dport);
228 return (1); /* We'll block unknown type of packet */
231 if (log_IsKept(LogDEBUG)) {
234 snprintf(dbuff + len, sizeof dbuff - len,
235 ", estab = %d, syn = %d, finrst = %d",
238 log_Printf(LogDEBUG, " Filter: proto = %s, %s\n",
239 filter_Proto2Nam(cproto), dbuff);
243 if (log_IsKept(LogDEBUG)) {
244 if (fp->f_srcop != OP_NONE) {
245 snprintf(dbuff, sizeof dbuff, ", src %s %d",
246 filter_Op2Nam(fp->f_srcop), fp->f_srcport);
250 if (fp->f_dstop != OP_NONE) {
251 snprintf(dbuff + len, sizeof dbuff - len,
252 ", dst %s %d", filter_Op2Nam(fp->f_dstop),
257 log_Printf(LogDEBUG, " rule = %d: Address match, "
258 "check against proto %s%s, action = %s\n",
259 n, filter_Proto2Nam(fp->f_proto),
260 dbuff, filter_Action2Nam(fp->f_action));
263 if (cproto == fp->f_proto) {
264 if ((fp->f_srcop == OP_NONE ||
265 PortMatch(fp->f_srcop, sport, fp->f_srcport)) &&
266 (fp->f_dstop == OP_NONE ||
267 PortMatch(fp->f_dstop, dport, fp->f_dstport)) &&
268 (fp->f_estab == 0 || estab) &&
269 (fp->f_syn == 0 || syn) &&
270 (fp->f_finrst == 0 || finrst)) {
275 /* Address is matched and no protocol specified. Make a decision. */
276 log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n,
277 filter_Action2Nam(fp->f_action));
281 log_Printf(LogDEBUG, " rule = %d: Address mismatch\n", n);
283 if (match != fp->f_invert) {
284 /* Take specified action */
285 if (fp->f_action < A_NONE)
286 fp = &filter->rule[n = fp->f_action];
288 return (fp->f_action != A_PERMIT);
294 return (1); /* No rule is mached. Deny this packet */
299 IcmpError(struct ip *pip, int code)
303 if (pip->ip_p != IPPROTO_ICMP) {
304 bp = mbuf_Alloc(cnt, MB_IPIN);
305 memcpy(MBUF_CTOP(bp), ptr, cnt);
307 ipcp_AddOutOctets(cnt);
316 PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter)
328 logit = log_IsKept(LogTCPIP) && filter->logok;
331 pip = (struct ip *) cp;
333 if (logit && loglen < sizeof logbuf) {
334 snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name);
335 loglen += strlen(logbuf + loglen);
337 ptop = (cp + (pip->ip_hl << 2));
341 if (logit && loglen < sizeof logbuf) {
342 icmph = (struct icmp *) ptop;
343 snprintf(logbuf + loglen, sizeof logbuf - loglen,
344 "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type);
345 loglen += strlen(logbuf + loglen);
346 snprintf(logbuf + loglen, sizeof logbuf - loglen,
347 "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type);
348 loglen += strlen(logbuf + loglen);
353 uh = (struct udphdr *) ptop;
354 if (pip->ip_tos == IPTOS_LOWDELAY)
357 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0 &&
358 ipcp_IsUrgentUdpPort(&bundle->ncp.ipcp, ntohs(uh->uh_sport),
359 ntohs(uh->uh_dport)))
362 if (logit && loglen < sizeof logbuf) {
363 snprintf(logbuf + loglen, sizeof logbuf - loglen,
364 "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
365 loglen += strlen(logbuf + loglen);
366 snprintf(logbuf + loglen, sizeof logbuf - loglen,
367 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
368 loglen += strlen(logbuf + loglen);
374 if (logit && loglen < sizeof logbuf) {
375 snprintf(logbuf + loglen, sizeof logbuf - loglen,
376 "GRE: %s ---> ", inet_ntoa(pip->ip_src));
377 loglen += strlen(logbuf + loglen);
378 snprintf(logbuf + loglen, sizeof logbuf - loglen,
379 "%s", inet_ntoa(pip->ip_dst));
380 loglen += strlen(logbuf + loglen);
385 #ifdef IPPROTO_OSPFIGP
386 case IPPROTO_OSPFIGP:
387 if (logit && loglen < sizeof logbuf) {
388 snprintf(logbuf + loglen, sizeof logbuf - loglen,
389 "OSPF: %s ---> ", inet_ntoa(pip->ip_src));
390 loglen += strlen(logbuf + loglen);
391 snprintf(logbuf + loglen, sizeof logbuf - loglen,
392 "%s", inet_ntoa(pip->ip_dst));
393 loglen += strlen(logbuf + loglen);
399 if (logit && loglen < sizeof logbuf) {
400 uh = (struct udphdr *) ptop;
401 snprintf(logbuf + loglen, sizeof logbuf - loglen,
402 "IPIP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
403 loglen += strlen(logbuf + loglen);
404 snprintf(logbuf + loglen, sizeof logbuf - loglen,
405 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
406 loglen += strlen(logbuf + loglen);
411 if (logit && loglen < sizeof logbuf) {
412 uh = (struct udphdr *) ptop;
413 snprintf(logbuf + loglen, sizeof logbuf - loglen,
414 "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
415 loglen += strlen(logbuf + loglen);
416 snprintf(logbuf + loglen, sizeof logbuf - loglen,
417 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
418 loglen += strlen(logbuf + loglen);
423 th = (struct tcphdr *) ptop;
424 if (pip->ip_tos == IPTOS_LOWDELAY)
427 if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0 &&
428 ipcp_IsUrgentTcpPort(&bundle->ncp.ipcp, ntohs(th->th_sport),
429 ntohs(th->th_dport)))
432 if (logit && loglen < sizeof logbuf) {
433 len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2);
434 snprintf(logbuf + loglen, sizeof logbuf - loglen,
435 "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport));
436 loglen += strlen(logbuf + loglen);
437 snprintf(logbuf + loglen, sizeof logbuf - loglen,
438 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport));
439 loglen += strlen(logbuf + loglen);
441 for (mask = TH_FIN; mask != 0x40; mask <<= 1) {
442 if (th->th_flags & mask) {
443 snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]);
444 loglen += strlen(logbuf + loglen);
448 snprintf(logbuf + loglen, sizeof logbuf - loglen,
449 " seq:%lx ack:%lx (%d/%d)",
450 (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb);
451 loglen += strlen(logbuf + loglen);
452 if ((th->th_flags & TH_SYN) && nb > 40) {
456 sp = (u_short *) ptop;
457 if (ntohs(sp[0]) == 0x0204) {
458 snprintf(logbuf + loglen, sizeof logbuf - loglen,
459 " MSS = %d", ntohs(sp[1]));
460 loglen += strlen(logbuf + loglen);
467 if (FilterCheck(pip, filter)) {
469 log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf);
476 /* Check Keep Alive filter */
478 if (FilterCheck(pip, &bundle->filter.alive))
479 log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf);
481 log_Printf(LogTCPIP, "%s\n", logbuf);
488 ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
494 if (bundle->ncp.ipcp.fsm.state != ST_OPENED) {
495 log_Printf(LogWARN, "ip_Input: IPCP not open - packet dropped\n");
500 mbuf_SetType(bp, MB_IPIN);
501 tun_fill_header(tun, AF_INET);
502 nb = mbuf_Length(bp);
503 if (nb > sizeof tun.data) {
504 log_Printf(LogWARN, "ip_Input: %s: Packet too large (got %d, max %d)\n",
505 l->name, nb, (int)(sizeof tun.data));
509 mbuf_Read(bp, tun.data, nb);
511 if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0)
514 pip = (struct ip *)tun.data;
515 if (!FilterCheck(pip, &bundle->filter.alive))
516 bundle_StartIdleTimer(bundle);
518 ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
520 nb += sizeof tun - sizeof tun.data;
521 nw = write(bundle->dev.fd, &tun, nb);
524 log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %s\n",
525 l->name, nb, strerror(errno));
527 log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %d\n", l->name, nb, nw);
534 ip_Enqueue(struct ipcp *ipcp, int pri, char *ptr, int count)
538 if (pri < 0 || pri >= IPCP_QUEUES(ipcp))
539 log_Printf(LogERROR, "Can't store in ip queue %d\n", pri);
542 * We allocate an extra 6 bytes, four at the front and two at the end.
543 * This is an optimisation so that we need to do less work in
544 * mbuf_Prepend() in acf_LayerPush() and proto_LayerPush() and
545 * appending in hdlc_LayerPush().
547 bp = mbuf_Alloc(count + 6, MB_IPOUT);
550 memcpy(MBUF_CTOP(bp), ptr, count);
551 mbuf_Enqueue(ipcp->Queue + pri, bp);
556 ip_DeleteQueue(struct ipcp *ipcp)
558 struct mqueue *queue;
560 for (queue = ipcp->Queue; queue < ipcp->Queue + IPCP_QUEUES(ipcp); queue++)
562 mbuf_Free(mbuf_Dequeue(queue));
566 ip_QueueLen(struct ipcp *ipcp)
568 struct mqueue *queue;
571 for (queue = ipcp->Queue; queue < ipcp->Queue + IPCP_QUEUES(ipcp); queue++)
572 result += queue->qlen;
578 ip_PushPacket(struct link *l, struct bundle *bundle)
580 struct ipcp *ipcp = &bundle->ncp.ipcp;
581 struct mqueue *queue;
586 if (ipcp->fsm.state != ST_OPENED)
589 queue = ipcp->Queue + IPCP_QUEUES(ipcp) - 1;
592 bp = mbuf_Contiguous(mbuf_Dequeue(queue));
593 cnt = mbuf_Length(bp);
594 pip = (struct ip *)MBUF_CTOP(bp);
595 if (!FilterCheck(pip, &bundle->filter.alive))
596 bundle_StartIdleTimer(bundle);
597 link_PushPacket(l, bp, bundle, 0, PROTO_IP);
598 ipcp_AddOutOctets(ipcp, cnt);
601 } while (queue-- != ipcp->Queue);