sbin/hammer/cmd_mirror.c: Stick with style(9) bracing style.
[dragonfly.git] / contrib / ipfilter / opt.c
blob825a5e346dd0fdfdf067f3b319a833c24724ceba
1 /*
2 * Copyright (C) 1993-2001 by Darren Reed.
4 * See the IPFILTER.LICENCE file for details on licencing.
5 */
6 #if defined(__sgi) && (IRIX > 602)
7 # include <sys/ptimers.h>
8 #endif
9 #include <stdio.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <sys/types.h>
13 #include <sys/time.h>
14 #include <sys/socket.h>
15 #include <netinet/in.h>
16 #include <netinet/in_systm.h>
17 #include <netinet/ip.h>
18 #ifndef linux
19 #include <netinet/ip_var.h>
20 #endif
21 #include <netinet/tcp.h>
22 #include <net/if.h>
23 #include <arpa/inet.h>
24 #include "ip_compat.h"
25 #include <netinet/tcpip.h>
26 #include "ip_fil.h"
27 #include "ipf.h"
29 #if !defined(lint)
30 static const char sccsid[] = "@(#)opt.c 1.8 4/10/96 (C) 1993-2000 Darren Reed";
31 static const char rcsid[] = "@(#)$Id: opt.c,v 2.2.2.3 2002/12/06 11:40:27 darrenr Exp $";
32 #endif
34 extern int opts;
36 struct ipopt_names ionames[] ={
37 { IPOPT_NOP, 0x000001, 1, "nop" },
38 { IPOPT_RR, 0x000002, 7, "rr" }, /* 1 route */
39 { IPOPT_ZSU, 0x000004, 3, "zsu" },
40 { IPOPT_MTUP, 0x000008, 3, "mtup" },
41 { IPOPT_MTUR, 0x000010, 3, "mtur" },
42 { IPOPT_ENCODE, 0x000020, 3, "encode" },
43 { IPOPT_TS, 0x000040, 8, "ts" }, /* 1 TS */
44 { IPOPT_TR, 0x000080, 3, "tr" },
45 { IPOPT_SECURITY,0x000100, 11, "sec" },
46 { IPOPT_SECURITY,0x000100, 11, "sec-class" },
47 { IPOPT_LSRR, 0x000200, 7, "lsrr" }, /* 1 route */
48 { IPOPT_E_SEC, 0x000400, 3, "e-sec" },
49 { IPOPT_CIPSO, 0x000800, 3, "cipso" },
50 { IPOPT_SATID, 0x001000, 4, "satid" },
51 { IPOPT_SSRR, 0x002000, 7, "ssrr" }, /* 1 route */
52 { IPOPT_ADDEXT, 0x004000, 3, "addext" },
53 { IPOPT_VISA, 0x008000, 3, "visa" },
54 { IPOPT_IMITD, 0x010000, 3, "imitd" },
55 { IPOPT_EIP, 0x020000, 3, "eip" },
56 { IPOPT_FINN, 0x040000, 3, "finn" },
57 { 0, 0, 0, (char *)NULL } /* must be last */
60 struct ipopt_names secclass[] = {
61 { IPSO_CLASS_RES4, 0x01, 0, "reserv-4" },
62 { IPSO_CLASS_TOPS, 0x02, 0, "topsecret" },
63 { IPSO_CLASS_SECR, 0x04, 0, "secret" },
64 { IPSO_CLASS_RES3, 0x08, 0, "reserv-3" },
65 { IPSO_CLASS_CONF, 0x10, 0, "confid" },
66 { IPSO_CLASS_UNCL, 0x20, 0, "unclass" },
67 { IPSO_CLASS_RES2, 0x40, 0, "reserv-2" },
68 { IPSO_CLASS_RES1, 0x80, 0, "reserv-1" },
69 { 0, 0, 0, NULL } /* must be last */
73 static u_char seclevel __P((char *));
74 int addipopt __P((char *, struct ipopt_names *, int, char *));
76 static u_char seclevel(slevel)
77 char *slevel;
79 struct ipopt_names *so;
81 for (so = secclass; so->on_name; so++)
82 if (!strcasecmp(slevel, so->on_name))
83 break;
85 if (!so->on_name) {
86 fprintf(stderr, "no such security level: %s\n", slevel);
87 return 0;
89 return (u_char)so->on_value;
93 int addipopt(op, io, len, class)
94 char *op;
95 struct ipopt_names *io;
96 int len;
97 char *class;
99 int olen = len;
100 struct in_addr ipadr;
101 u_short val;
102 u_char lvl;
103 char *s;
105 if ((len + io->on_siz) > 48) {
106 fprintf(stderr, "options too long\n");
107 return 0;
109 len += io->on_siz;
110 *op++ = io->on_value;
111 if (io->on_siz > 1) {
112 s = op;
113 *op++ = io->on_siz;
114 *op++ = IPOPT_MINOFF;
116 if (class) {
117 switch (io->on_value)
119 case IPOPT_SECURITY :
120 lvl = seclevel(class);
121 *(op - 1) = lvl;
122 break;
123 case IPOPT_LSRR :
124 case IPOPT_SSRR :
125 ipadr.s_addr = inet_addr(class);
126 s[IPOPT_OLEN] = IPOPT_MINOFF - 1 + 4;
127 bcopy((char *)&ipadr, op, sizeof(ipadr));
128 break;
129 case IPOPT_SATID :
130 val = atoi(class);
131 bcopy((char *)&val, op, 2);
132 break;
136 op += io->on_siz - 3;
137 if (len & 3) {
138 *op++ = IPOPT_NOP;
139 len++;
142 if (opts & OPT_DEBUG)
143 fprintf(stderr, "bo: %s %d %#x: %d\n",
144 io->on_name, io->on_value, io->on_bit, len);
145 return len - olen;
149 u_32_t buildopts(cp, op, len)
150 char *cp, *op;
151 int len;
153 struct ipopt_names *io;
154 u_32_t msk = 0;
155 char *s, *t;
156 int inc;
158 for (s = strtok(cp, ","); s; s = strtok(NULL, ",")) {
159 if ((t = strchr(s, '=')))
160 *t++ = '\0';
161 for (io = ionames; io->on_name; io++) {
162 if (strcasecmp(s, io->on_name) || (msk & io->on_bit))
163 continue;
164 if ((inc = addipopt(op, io, len, t))) {
165 op += inc;
166 len += inc;
168 msk |= io->on_bit;
169 break;
171 if (!io->on_name) {
172 fprintf(stderr, "unknown IP option name %s\n", s);
173 return 0;
176 *op++ = IPOPT_EOL;
177 len++;
178 return len;