ipsopt.c revision 92686
1/* 2 * Copyright (C) 1995-1998 by Darren Reed. 3 * 4 * See the IPFILTER.LICENCE file for details on licencing. 5 */ 6#ifdef __sgi 7# include <sys/ptimers.h> 8#endif 9#include <sys/param.h> 10#include <stdio.h> 11#include <string.h> 12#include <stdlib.h> 13#include <sys/types.h> 14#include <sys/time.h> 15#include <sys/socket.h> 16#include <netinet/in.h> 17#include <netinet/in_systm.h> 18#include <netinet/ip.h> 19#ifndef linux 20#include <netinet/ip_var.h> 21#endif 22#include <netinet/tcp.h> 23#include <arpa/inet.h> 24#include "ipsend.h" 25 26#if !defined(lint) 27static const char sccsid[] = "@(#)ipsopt.c 1.2 1/11/96 (C)1995 Darren Reed"; 28static const char rcsid[] = "@(#)$Id: ipsopt.c,v 2.1.4.3 2002/02/22 15:32:58 darrenr Exp $"; 29#endif 30 31 32struct ipopt_names ionames[] = { 33 { IPOPT_EOL, 0x01, 1, "eol" }, 34 { IPOPT_NOP, 0x02, 1, "nop" }, 35 { IPOPT_RR, 0x04, 3, "rr" }, /* 1 route */ 36 { IPOPT_TS, 0x08, 8, "ts" }, /* 1 TS */ 37 { IPOPT_SECURITY, 0x08, 11, "sec-level" }, 38 { IPOPT_LSRR, 0x10, 7, "lsrr" }, /* 1 route */ 39 { IPOPT_SATID, 0x20, 4, "satid" }, 40 { IPOPT_SSRR, 0x40, 7, "ssrr" }, /* 1 route */ 41 { 0, 0, 0, NULL } /* must be last */ 42}; 43 44struct ipopt_names secnames[] = { 45 { IPOPT_SECUR_UNCLASS, 0x0100, 0, "unclass" }, 46 { IPOPT_SECUR_CONFID, 0x0200, 0, "confid" }, 47 { IPOPT_SECUR_EFTO, 0x0400, 0, "efto" }, 48 { IPOPT_SECUR_MMMM, 0x0800, 0, "mmmm" }, 49 { IPOPT_SECUR_RESTR, 0x1000, 0, "restr" }, 50 { IPOPT_SECUR_SECRET, 0x2000, 0, "secret" }, 51 { IPOPT_SECUR_TOPSECRET, 0x4000,0, "topsecret" }, 52 { 0, 0, 0, NULL } /* must be last */ 53}; 54 55 56u_short seclevel(slevel) 57char *slevel; 58{ 59 struct ipopt_names *so; 60 61 for (so = secnames; so->on_name; so++) 62 if (!strcasecmp(slevel, so->on_name)) 63 break; 64 65 if (!so->on_name) { 66 fprintf(stderr, "no such security level: %s\n", slevel); 67 return 0; 68 } 69 return so->on_value; 70} 71 72 73int addipopt(op, io, len, class) 74char *op; 75struct ipopt_names *io; 76int len; 77char *class; 78{ 79 struct in_addr ipadr; 80 int olen = len, srr = 0; 81 u_short val; 82 u_char lvl; 83 char *s = op, *t; 84 85 if ((len + io->on_siz) > 48) { 86 fprintf(stderr, "options too long\n"); 87 return 0; 88 } 89 len += io->on_siz; 90 *op++ = io->on_value; 91 if (io->on_siz > 1) { 92 /* 93 * Allow option to specify RR buffer length in bytes. 94 */ 95 if (io->on_value == IPOPT_RR) { 96 val = (class && *class) ? atoi(class) : 4; 97 *op++ = val + io->on_siz; 98 len += val; 99 } else 100 *op++ = io->on_siz; 101 *op++ = IPOPT_MINOFF; 102 103 while (class && *class) { 104 t = NULL; 105 switch (io->on_value) 106 { 107 case IPOPT_SECURITY : 108 lvl = seclevel(class); 109 *(op - 1) = lvl; 110 break; 111 case IPOPT_LSRR : 112 case IPOPT_SSRR : 113 if ((t = strchr(class, ','))) 114 *t = '\0'; 115 ipadr.s_addr = inet_addr(class); 116 srr++; 117 bcopy((char *)&ipadr, op, sizeof(ipadr)); 118 op += sizeof(ipadr); 119 break; 120 case IPOPT_SATID : 121 val = atoi(class); 122 bcopy((char *)&val, op, 2); 123 break; 124 } 125 126 if (t) 127 *t++ = ','; 128 class = t; 129 } 130 if (srr) 131 s[IPOPT_OLEN] = IPOPT_MINOFF - 1 + 4 * srr; 132 if (io->on_value == IPOPT_RR) 133 op += val; 134 else 135 op += io->on_siz - 3; 136 } 137 return len - olen; 138} 139 140 141u_32_t buildopts(cp, op, len) 142char *cp, *op; 143int len; 144{ 145 struct ipopt_names *io; 146 u_32_t msk = 0; 147 char *s, *t; 148 int inc, lastop = -1; 149 150 for (s = strtok(cp, ","); s; s = strtok(NULL, ",")) { 151 if ((t = strchr(s, '='))) 152 *t++ = '\0'; 153 for (io = ionames; io->on_name; io++) { 154 if (strcasecmp(s, io->on_name) || (msk & io->on_bit)) 155 continue; 156 lastop = io->on_value; 157 if ((inc = addipopt(op, io, len, t))) { 158 op += inc; 159 len += inc; 160 } 161 msk |= io->on_bit; 162 break; 163 } 164 if (!io->on_name) { 165 fprintf(stderr, "unknown IP option name %s\n", s); 166 return 0; 167 } 168 } 169 170 if (len & 3) { 171 while (len & 3) { 172 *op++ = ((len & 3) == 3) ? IPOPT_EOL : IPOPT_NOP; 173 len++; 174 } 175 } else { 176 if (lastop != IPOPT_EOL) { 177 if (lastop == IPOPT_NOP) 178 *(op - 1) = IPOPT_EOL; 179 else { 180 *op++ = IPOPT_NOP; 181 *op++ = IPOPT_NOP; 182 *op++ = IPOPT_NOP; 183 *op = IPOPT_EOL; 184 len += 4; 185 } 186 } 187 } 188 return len; 189} 190