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