Merge from vendor branch NCURSES:
[dragonfly.git] / contrib / ipfilter / opt.c
1 /*
2  * Copyright (C) 1993-2001 by Darren Reed.
3  *
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"
28
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
33
34 extern  int     opts;
35
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 */
58 };
59
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 */
70 };
71
72
73 static  u_char  seclevel __P((char *));
74 int addipopt __P((char *, struct ipopt_names *, int, char *));
75
76 static u_char seclevel(slevel)
77 char *slevel;
78 {
79         struct ipopt_names *so;
80
81         for (so = secclass; so->on_name; so++)
82                 if (!strcasecmp(slevel, so->on_name))
83                         break;
84
85         if (!so->on_name) {
86                 fprintf(stderr, "no such security level: %s\n", slevel);
87                 return 0;
88         }
89         return (u_char)so->on_value;
90 }
91
92
93 int addipopt(op, io, len, class)
94 char *op;
95 struct ipopt_names *io;
96 int len;
97 char *class;
98 {
99         int olen = len;
100         struct in_addr ipadr;
101         u_short val;
102         u_char lvl;
103         char *s;
104
105         if ((len + io->on_siz) > 48) {
106                 fprintf(stderr, "options too long\n");
107                 return 0;
108         }
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;
115
116                 if (class) {
117                         switch (io->on_value)
118                         {
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;
133                         }
134                 }
135
136                 op += io->on_siz - 3;
137                 if (len & 3) {
138                         *op++ = IPOPT_NOP;
139                         len++;
140                 }
141         }
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;
146 }
147
148
149 u_32_t buildopts(cp, op, len)
150 char *cp, *op;
151 int len;
152 {
153         struct ipopt_names *io;
154         u_32_t msk = 0;
155         char *s, *t;
156         int inc;
157
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;
167                         }
168                         msk |= io->on_bit;
169                         break;
170                 }
171                 if (!io->on_name) {
172                         fprintf(stderr, "unknown IP option name %s\n", s);
173                         return 0;
174                 }
175         }
176         *op++ = IPOPT_EOL;
177         len++;
178         return len;
179 }