ipsopt.c revision 31183
122514Sdarrenr/* 231183Speter * Copyright (C) 1995-1997 by Darren Reed. 322514Sdarrenr * 431183Speter * Redistribution and use in source and binary forms are permitted 531183Speter * provided that this notice is preserved and due credit is given 631183Speter * to the original author and the contributors. 722514Sdarrenr */ 831183Speter#if !defined(lint) 931183Speterstatic const char sccsid[] = "@(#)ipsopt.c 1.2 1/11/96 (C)1995 Darren Reed"; 1031183Speterstatic const char rcsid[] = "@(#)$Id: ipsopt.c,v 2.0.2.10 1997/09/28 07:13:28 darrenr Exp $"; 1122514Sdarrenr#endif 1222514Sdarrenr#include <stdio.h> 1322514Sdarrenr#include <string.h> 1431183Speter#include <stdlib.h> 1522514Sdarrenr#include <sys/types.h> 1622514Sdarrenr#include <sys/time.h> 1722514Sdarrenr#include <sys/socket.h> 1822514Sdarrenr#include <netinet/in.h> 1922514Sdarrenr#include <netinet/in_systm.h> 2022514Sdarrenr#include <netinet/ip.h> 2131183Speter#ifndef linux 2231183Speter#include <netinet/ip_var.h> 2331183Speter#endif 2431183Speter#include <netinet/tcp.h> 2531183Speter#include <arpa/inet.h> 2631183Speter#include "ipsend.h" 2722514Sdarrenr 2824583Sdarrenr 2924583Sdarrenr#ifndef __P 3024583Sdarrenr# ifdef __STDC__ 3124583Sdarrenr# define __P(x) x 3224583Sdarrenr# else 3324583Sdarrenr# define __P(x) () 3424583Sdarrenr# endif 3524583Sdarrenr#endif 3624583Sdarrenr 3724583Sdarrenr 3822514Sdarrenrstruct ipopt_names ionames[] = { 3922514Sdarrenr { IPOPT_EOL, 0x01, 1, "eol" }, 4022514Sdarrenr { IPOPT_NOP, 0x02, 1, "nop" }, 4131183Speter { IPOPT_RR, 0x04, 3, "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 6222514Sdarrenru_short seclevel(slevel) 6322514Sdarrenrchar *slevel; 6422514Sdarrenr{ 6522514Sdarrenr struct ipopt_names *so; 6622514Sdarrenr 6722514Sdarrenr for (so = secnames; so->on_name; so++) 6822514Sdarrenr if (!strcasecmp(slevel, so->on_name)) 6922514Sdarrenr break; 7022514Sdarrenr 7122514Sdarrenr if (!so->on_name) { 7222514Sdarrenr fprintf(stderr, "no such security level: %s\n", slevel); 7322514Sdarrenr return 0; 7422514Sdarrenr } 7522514Sdarrenr return so->on_value; 7622514Sdarrenr} 7722514Sdarrenr 7822514Sdarrenr 7931183Speterint addipopt(op, io, len, class) 8031183Speterchar *op; 8131183Speterstruct ipopt_names *io; 8231183Speterint len; 8331183Speterchar *class; 8431183Speter{ 8531183Speter struct in_addr ipadr; 8631183Speter int olen = len, srr = 0; 8731183Speter u_short val; 8831183Speter u_char lvl; 8931183Speter char *s = op, *t; 9031183Speter 9131183Speter if ((len + io->on_siz) > 48) { 9231183Speter fprintf(stderr, "options too long\n"); 9331183Speter return 0; 9431183Speter } 9531183Speter len += io->on_siz; 9631183Speter *op++ = io->on_value; 9731183Speter if (io->on_siz > 1) { 9831183Speter /* 9931183Speter * Allow option to specify RR buffer length in bytes. 10031183Speter */ 10131183Speter if (io->on_value == IPOPT_RR) { 10231183Speter val = (class && *class) ? atoi(class) : 4; 10331183Speter *op++ = val + io->on_siz; 10431183Speter len += val; 10531183Speter } else 10631183Speter *op++ = io->on_siz; 10731183Speter *op++ = IPOPT_MINOFF; 10831183Speter 10931183Speter while (class && *class) { 11031183Speter t = NULL; 11131183Speter switch (io->on_value) 11231183Speter { 11331183Speter case IPOPT_SECURITY : 11431183Speter lvl = seclevel(class); 11531183Speter *(op - 1) = lvl; 11631183Speter break; 11731183Speter case IPOPT_LSRR : 11831183Speter case IPOPT_SSRR : 11931183Speter if ((t = strchr(class, ','))) 12031183Speter *t = '\0'; 12131183Speter ipadr.s_addr = inet_addr(class); 12231183Speter srr++; 12331183Speter bcopy((char *)&ipadr, op, sizeof(ipadr)); 12431183Speter op += sizeof(ipadr); 12531183Speter break; 12631183Speter case IPOPT_SATID : 12731183Speter val = atoi(class); 12831183Speter bcopy((char *)&val, op, 2); 12931183Speter break; 13031183Speter } 13131183Speter 13231183Speter if (t) 13331183Speter *t++ = ','; 13431183Speter class = t; 13531183Speter } 13631183Speter if (srr) 13731183Speter s[IPOPT_OLEN] = IPOPT_MINOFF - 1 + 4 * srr; 13831183Speter if (io->on_value == IPOPT_RR) 13931183Speter op += val; 14031183Speter else 14131183Speter op += io->on_siz - 3; 14231183Speter } 14331183Speter return len - olen; 14431183Speter} 14531183Speter 14631183Speter 14731183Speteru_32_t buildopts(cp, op, len) 14822514Sdarrenrchar *cp, *op; 14931183Speterint len; 15022514Sdarrenr{ 15122514Sdarrenr struct ipopt_names *io; 15231183Speter u_32_t msk = 0; 15322514Sdarrenr char *s, *t; 15431183Speter int inc, lastop = -1; 15522514Sdarrenr 15622514Sdarrenr for (s = strtok(cp, ","); s; s = strtok(NULL, ",")) { 15722514Sdarrenr if ((t = strchr(s, '='))) 15822514Sdarrenr *t++ = '\0'; 15922514Sdarrenr for (io = ionames; io->on_name; io++) { 16022514Sdarrenr if (strcasecmp(s, io->on_name) || (msk & io->on_bit)) 16122514Sdarrenr continue; 16231183Speter lastop = io->on_value; 16331183Speter if ((inc = addipopt(op, io, len, t))) { 16431183Speter op += inc; 16531183Speter len += inc; 16622514Sdarrenr } 16722514Sdarrenr msk |= io->on_bit; 16822514Sdarrenr break; 16922514Sdarrenr } 17022514Sdarrenr if (!io->on_name) { 17122514Sdarrenr fprintf(stderr, "unknown IP option name %s\n", s); 17222514Sdarrenr return 0; 17322514Sdarrenr } 17422514Sdarrenr } 17531183Speter 17631183Speter if (len & 3) { 17731183Speter while (len & 3) { 17831183Speter *op++ = ((len & 3) == 3) ? IPOPT_EOL : IPOPT_NOP; 17931183Speter len++; 18031183Speter } 18131183Speter } else { 18231183Speter if (lastop != IPOPT_EOL) { 18331183Speter if (lastop == IPOPT_NOP) 18431183Speter *(op - 1) = IPOPT_EOL; 18531183Speter else { 18631183Speter *op++ = IPOPT_NOP; 18731183Speter *op++ = IPOPT_NOP; 18831183Speter *op++ = IPOPT_NOP; 18931183Speter *op = IPOPT_EOL; 19031183Speter len += 4; 19131183Speter } 19231183Speter } 19331183Speter } 19422514Sdarrenr return len; 19522514Sdarrenr} 196