ipsopt.c revision 22514
1/* 2 * (C)opyright 1995 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 ? 7 */ 8#if !defined(lint) && defined(LIBC_SCCS) 9static char sccsid[] = "@(#)ipsopt.c 1.2 1/11/96 (C)1995 Darren Reed"; 10#endif 11#include <stdio.h> 12#include <string.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#include "ip_compat.h" 20 21struct ipopt_names { 22 int on_value; 23 int on_bit; 24 int on_siz; 25 char *on_name; 26}; 27 28struct ipopt_names ionames[] = { 29 { IPOPT_EOL, 0x01, 1, "eol" }, 30 { IPOPT_NOP, 0x02, 1, "nop" }, 31 { IPOPT_RR, 0x04, 7, "rr" }, /* 1 route */ 32 { IPOPT_TS, 0x08, 8, "ts" }, /* 1 TS */ 33 { IPOPT_SECURITY, 0x08, 11, "sec-level" }, 34 { IPOPT_LSRR, 0x10, 7, "lsrr" }, /* 1 route */ 35 { IPOPT_SATID, 0x20, 4, "satid" }, 36 { IPOPT_SSRR, 0x40, 7, "ssrr" }, /* 1 route */ 37 { 0, 0, 0, NULL } /* must be last */ 38}; 39 40struct ipopt_names secnames[] = { 41 { IPOPT_SECUR_UNCLASS, 0x0100, 0, "unclass" }, 42 { IPOPT_SECUR_CONFID, 0x0200, 0, "confid" }, 43 { IPOPT_SECUR_EFTO, 0x0400, 0, "efto" }, 44 { IPOPT_SECUR_MMMM, 0x0800, 0, "mmmm" }, 45 { IPOPT_SECUR_RESTR, 0x1000, 0, "restr" }, 46 { IPOPT_SECUR_SECRET, 0x2000, 0, "secret" }, 47 { IPOPT_SECUR_TOPSECRET, 0x4000,0, "topsecret" }, 48 { 0, 0, 0, NULL } /* must be last */ 49}; 50 51 52u_short seclevel(slevel) 53char *slevel; 54{ 55 struct ipopt_names *so; 56 57 for (so = secnames; so->on_name; so++) 58 if (!strcasecmp(slevel, so->on_name)) 59 break; 60 61 if (!so->on_name) { 62 fprintf(stderr, "no such security level: %s\n", slevel); 63 return 0; 64 } 65 return so->on_value; 66} 67 68 69u_long optname(cp, op) 70char *cp, *op; 71{ 72 struct ipopt_names *io; 73 u_short lvl; 74 u_long msk = 0; 75 char *s, *t; 76 int len = 0; 77 78 for (s = strtok(cp, ","); s; s = strtok(NULL, ",")) { 79 if ((t = strchr(s, '='))) 80 *t++ = '\0'; 81 for (io = ionames; io->on_name; io++) { 82 if (strcasecmp(s, io->on_name) || (msk & io->on_bit)) 83 continue; 84 if ((len + io->on_siz) > 48) { 85 fprintf(stderr, "options too long\n"); 86 return 0; 87 } 88 len += io->on_siz; 89 *op++ = io->on_value; 90 if (io->on_siz > 1) { 91 *op++ = io->on_siz; 92 *op++ = IPOPT_MINOFF; 93 94 if (t && !strcasecmp(s, "sec-level")) { 95 lvl = seclevel(t); 96 bcopy(&lvl, op, sizeof(lvl)); 97 } 98 op += io->on_siz - 3; 99 } 100 msk |= io->on_bit; 101 break; 102 } 103 if (!io->on_name) { 104 fprintf(stderr, "unknown IP option name %s\n", s); 105 return 0; 106 } 107 } 108 *op++ = IPOPT_EOL; 109 len++; 110 return len; 111} 112