ipsopt.c revision 24583
122514Sdarrenr/* 222514Sdarrenr * (C)opyright 1995 by Darren Reed. 322514Sdarrenr * 422514Sdarrenr * This code may be freely distributed as long as it retains this notice 522514Sdarrenr * and is not changed in any way. The author accepts no responsibility 622514Sdarrenr * for the use of this software. I hate legaleese, don't you ? 722514Sdarrenr */ 822514Sdarrenr#if !defined(lint) && defined(LIBC_SCCS) 922514Sdarrenrstatic char sccsid[] = "@(#)ipsopt.c 1.2 1/11/96 (C)1995 Darren Reed"; 1022514Sdarrenr#endif 1122514Sdarrenr#include <stdio.h> 1222514Sdarrenr#include <string.h> 1322514Sdarrenr#include <sys/types.h> 1422514Sdarrenr#include <sys/time.h> 1522514Sdarrenr#include <sys/socket.h> 1622514Sdarrenr#include <netinet/in.h> 1722514Sdarrenr#include <netinet/in_systm.h> 1822514Sdarrenr#include <netinet/ip.h> 1922514Sdarrenr#include "ip_compat.h" 2022514Sdarrenr 2124583Sdarrenr 2224583Sdarrenr#ifndef __P 2324583Sdarrenr# ifdef __STDC__ 2424583Sdarrenr# define __P(x) x 2524583Sdarrenr# else 2624583Sdarrenr# define __P(x) () 2724583Sdarrenr# endif 2824583Sdarrenr#endif 2924583Sdarrenr 3024583Sdarrenr 3122514Sdarrenrstruct ipopt_names { 3222514Sdarrenr int on_value; 3322514Sdarrenr int on_bit; 3422514Sdarrenr int on_siz; 3522514Sdarrenr char *on_name; 3622514Sdarrenr}; 3722514Sdarrenr 3822514Sdarrenrstruct ipopt_names ionames[] = { 3922514Sdarrenr { IPOPT_EOL, 0x01, 1, "eol" }, 4022514Sdarrenr { IPOPT_NOP, 0x02, 1, "nop" }, 4122514Sdarrenr { IPOPT_RR, 0x04, 7, "rr" }, /* 1 route */ 4222514Sdarrenr { IPOPT_TS, 0x08, 8, "ts" }, /* 1 TS */ 4322514Sdarrenr { IPOPT_SECURITY, 0x08, 11, "sec-level" }, 4422514Sdarrenr { IPOPT_LSRR, 0x10, 7, "lsrr" }, /* 1 route */ 4522514Sdarrenr { IPOPT_SATID, 0x20, 4, "satid" }, 4622514Sdarrenr { IPOPT_SSRR, 0x40, 7, "ssrr" }, /* 1 route */ 4722514Sdarrenr { 0, 0, 0, NULL } /* must be last */ 4822514Sdarrenr}; 4922514Sdarrenr 5022514Sdarrenrstruct ipopt_names secnames[] = { 5122514Sdarrenr { IPOPT_SECUR_UNCLASS, 0x0100, 0, "unclass" }, 5222514Sdarrenr { IPOPT_SECUR_CONFID, 0x0200, 0, "confid" }, 5322514Sdarrenr { IPOPT_SECUR_EFTO, 0x0400, 0, "efto" }, 5422514Sdarrenr { IPOPT_SECUR_MMMM, 0x0800, 0, "mmmm" }, 5522514Sdarrenr { IPOPT_SECUR_RESTR, 0x1000, 0, "restr" }, 5622514Sdarrenr { IPOPT_SECUR_SECRET, 0x2000, 0, "secret" }, 5722514Sdarrenr { IPOPT_SECUR_TOPSECRET, 0x4000,0, "topsecret" }, 5822514Sdarrenr { 0, 0, 0, NULL } /* must be last */ 5922514Sdarrenr}; 6022514Sdarrenr 6122514Sdarrenr 6224583Sdarrenru_short seclevel __P((char *)); 6324583Sdarrenru_long optname __P((char *, char *)); 6424583Sdarrenr 6524583Sdarrenr 6622514Sdarrenru_short seclevel(slevel) 6722514Sdarrenrchar *slevel; 6822514Sdarrenr{ 6922514Sdarrenr struct ipopt_names *so; 7022514Sdarrenr 7122514Sdarrenr for (so = secnames; so->on_name; so++) 7222514Sdarrenr if (!strcasecmp(slevel, so->on_name)) 7322514Sdarrenr break; 7422514Sdarrenr 7522514Sdarrenr if (!so->on_name) { 7622514Sdarrenr fprintf(stderr, "no such security level: %s\n", slevel); 7722514Sdarrenr return 0; 7822514Sdarrenr } 7922514Sdarrenr return so->on_value; 8022514Sdarrenr} 8122514Sdarrenr 8222514Sdarrenr 8322514Sdarrenru_long optname(cp, op) 8422514Sdarrenrchar *cp, *op; 8522514Sdarrenr{ 8622514Sdarrenr struct ipopt_names *io; 8722514Sdarrenr u_short lvl; 8822514Sdarrenr u_long msk = 0; 8922514Sdarrenr char *s, *t; 9022514Sdarrenr int len = 0; 9122514Sdarrenr 9222514Sdarrenr for (s = strtok(cp, ","); s; s = strtok(NULL, ",")) { 9322514Sdarrenr if ((t = strchr(s, '='))) 9422514Sdarrenr *t++ = '\0'; 9522514Sdarrenr for (io = ionames; io->on_name; io++) { 9622514Sdarrenr if (strcasecmp(s, io->on_name) || (msk & io->on_bit)) 9722514Sdarrenr continue; 9822514Sdarrenr if ((len + io->on_siz) > 48) { 9922514Sdarrenr fprintf(stderr, "options too long\n"); 10022514Sdarrenr return 0; 10122514Sdarrenr } 10222514Sdarrenr len += io->on_siz; 10322514Sdarrenr *op++ = io->on_value; 10422514Sdarrenr if (io->on_siz > 1) { 10522514Sdarrenr *op++ = io->on_siz; 10622514Sdarrenr *op++ = IPOPT_MINOFF; 10722514Sdarrenr 10822514Sdarrenr if (t && !strcasecmp(s, "sec-level")) { 10922514Sdarrenr lvl = seclevel(t); 11022514Sdarrenr bcopy(&lvl, op, sizeof(lvl)); 11122514Sdarrenr } 11222514Sdarrenr op += io->on_siz - 3; 11322514Sdarrenr } 11422514Sdarrenr msk |= io->on_bit; 11522514Sdarrenr break; 11622514Sdarrenr } 11722514Sdarrenr if (!io->on_name) { 11822514Sdarrenr fprintf(stderr, "unknown IP option name %s\n", s); 11922514Sdarrenr return 0; 12022514Sdarrenr } 12122514Sdarrenr } 12222514Sdarrenr *op++ = IPOPT_EOL; 12322514Sdarrenr len++; 12422514Sdarrenr return len; 12522514Sdarrenr} 126