ipsopt.c revision 130887
118334Speter/* 218334Speter * Copyright (C) 1995-1998 by Darren Reed. 318334Speter * 418334Speter * See the IPFILTER.LICENCE file for details on licencing. 518334Speter */ 618334Speter#if defined(__sgi) && (IRIX > 602) 718334Speter# include <sys/ptimers.h> 818334Speter#endif 918334Speter#include <sys/param.h> 1018334Speter#include <stdio.h> 1118334Speter#include <string.h> 1218334Speter#include <stdlib.h> 1318334Speter#include <sys/types.h> 1418334Speter#include <sys/time.h> 1518334Speter#include <sys/socket.h> 1618334Speter#include <netinet/in.h> 1718334Speter#include <netinet/in_systm.h> 1818334Speter#include <netinet/ip.h> 1918334Speter#ifndef linux 2018334Speter#include <netinet/ip_var.h> 2118334Speter#endif 2218334Speter#include <netinet/tcp.h> 2318334Speter#include <arpa/inet.h> 2418334Speter#include "ipsend.h" 2518334Speter 2618334Speter#if !defined(lint) 2718334Speterstatic const char sccsid[] = "@(#)ipsopt.c 1.2 1/11/96 (C)1995 Darren Reed"; 2818334Speterstatic const char rcsid[] = "@(#)$Id: ipsopt.c,v 2.1.4.5 2004/04/10 11:50:52 darrenr Exp $"; 2918334Speter#endif 3018334Speter 3118334Speter 3218334Speterstruct ipopt_names ionames[] = { 3318334Speter { IPOPT_EOL, 0x01, 1, "eol" }, 3418334Speter { IPOPT_NOP, 0x02, 1, "nop" }, 3518334Speter { IPOPT_RR, 0x04, 3, "rr" }, /* 1 route */ 3618334Speter { IPOPT_TS, 0x08, 8, "ts" }, /* 1 TS */ 3718334Speter { IPOPT_SECURITY, 0x08, 11, "sec-level" }, 3818334Speter { IPOPT_LSRR, 0x10, 7, "lsrr" }, /* 1 route */ 3918334Speter { IPOPT_SATID, 0x20, 4, "satid" }, 4018334Speter { IPOPT_SSRR, 0x40, 7, "ssrr" }, /* 1 route */ 4118334Speter { 0, 0, 0, NULL } /* must be last */ 4218334Speter}; 4318334Speter 4418334Speterstruct ipopt_names secnames[] = { 4518334Speter { IPOPT_SECUR_UNCLASS, 0x0100, 0, "unclass" }, 4618334Speter { IPOPT_SECUR_CONFID, 0x0200, 0, "confid" }, 4718334Speter { IPOPT_SECUR_EFTO, 0x0400, 0, "efto" }, 4818334Speter { IPOPT_SECUR_MMMM, 0x0800, 0, "mmmm" }, 4918334Speter { IPOPT_SECUR_RESTR, 0x1000, 0, "restr" }, 5018334Speter { IPOPT_SECUR_SECRET, 0x2000, 0, "secret" }, 5118334Speter { IPOPT_SECUR_TOPSECRET, 0x4000,0, "topsecret" }, 5218334Speter { 0, 0, 0, NULL } /* must be last */ 5318334Speter}; 5418334Speter 5518334Speter 5618334Speteru_short seclevel(slevel) 5718334Speterchar *slevel; 5818334Speter{ 5918334Speter struct ipopt_names *so; 6018334Speter 6118334Speter for (so = secnames; so->on_name; so++) 6218334Speter if (!strcasecmp(slevel, so->on_name)) 6318334Speter break; 6418334Speter 6518334Speter if (!so->on_name) { 6618334Speter fprintf(stderr, "no such security level: %s\n", slevel); 6718334Speter return 0; 6818334Speter } 6918334Speter return so->on_value; 7018334Speter} 7118334Speter 7218334Speter 7318334Speterint addipopt(op, io, len, class) 7418334Speterchar *op; 7518334Speterstruct ipopt_names *io; 7618334Speterint len; 7718334Speterchar *class; 7818334Speter{ 7918334Speter struct in_addr ipadr; 8018334Speter int olen = len, srr = 0; 8118334Speter u_short val; 8218334Speter u_char lvl; 8318334Speter char *s = op, *t; 8418334Speter 8518334Speter if ((len + io->on_siz) > 48) { 8618334Speter fprintf(stderr, "options too long\n"); 8718334Speter return 0; 8818334Speter } 8918334Speter len += io->on_siz; 9018334Speter *op++ = io->on_value; 9118334Speter if (io->on_siz > 1) { 9218334Speter /* 9318334Speter * Allow option to specify RR buffer length in bytes. 9418334Speter */ 9518334Speter if (io->on_value == IPOPT_RR) { 9618334Speter val = (class && *class) ? atoi(class) : 4; 9718334Speter *op++ = val + io->on_siz; 9818334Speter len += val; 9918334Speter } else 10018334Speter *op++ = io->on_siz; 10118334Speter if (io->on_value == IPOPT_TS) 10218334Speter *op++ = IPOPT_MINOFF + 1; 10318334Speter else 10418334Speter *op++ = IPOPT_MINOFF; 10518334Speter 10618334Speter while (class && *class) { 10718334Speter t = NULL; 10818334Speter switch (io->on_value) 10918334Speter { 11018334Speter case IPOPT_SECURITY : 11118334Speter lvl = seclevel(class); 11218334Speter *(op - 1) = lvl; 11318334Speter break; 11418334Speter case IPOPT_LSRR : 11518334Speter case IPOPT_SSRR : 11618334Speter if ((t = strchr(class, ','))) 11718334Speter *t = '\0'; 11818334Speter ipadr.s_addr = inet_addr(class); 11918334Speter srr++; 12018334Speter bcopy((char *)&ipadr, op, sizeof(ipadr)); 12118334Speter op += sizeof(ipadr); 12218334Speter break; 12318334Speter case IPOPT_SATID : 12418334Speter val = atoi(class); 12518334Speter bcopy((char *)&val, op, 2); 12618334Speter break; 12718334Speter } 12818334Speter 12918334Speter if (t) 13018334Speter *t++ = ','; 13118334Speter class = t; 13218334Speter } 13318334Speter if (srr) 13418334Speter s[IPOPT_OLEN] = IPOPT_MINOFF - 1 + 4 * srr; 13518334Speter if (io->on_value == IPOPT_RR) 13618334Speter op += val; 13718334Speter else 13818334Speter op += io->on_siz - 3; 13918334Speter } 14018334Speter return len - olen; 14118334Speter} 14218334Speter 14318334Speter 14418334Speteru_32_t buildopts(cp, op, len) 14518334Speterchar *cp, *op; 14618334Speterint len; 14718334Speter{ 14818334Speter struct ipopt_names *io; 14918334Speter u_32_t msk = 0; 15018334Speter char *s, *t; 15118334Speter int inc, lastop = -1; 15218334Speter 15318334Speter for (s = strtok(cp, ","); s; s = strtok(NULL, ",")) { 15418334Speter if ((t = strchr(s, '='))) 15518334Speter *t++ = '\0'; 15618334Speter for (io = ionames; io->on_name; io++) { 15718334Speter if (strcasecmp(s, io->on_name) || (msk & io->on_bit)) 15818334Speter continue; 15918334Speter lastop = io->on_value; 16018334Speter if ((inc = addipopt(op, io, len, t))) { 16118334Speter op += inc; 16218334Speter len += inc; 16318334Speter } 16418334Speter msk |= io->on_bit; 16518334Speter break; 16618334Speter } 16718334Speter if (!io->on_name) { 16818334Speter fprintf(stderr, "unknown IP option name %s\n", s); 16918334Speter return 0; 17018334Speter } 17118334Speter } 17218334Speter 17318334Speter if (len & 3) { 17418334Speter while (len & 3) { 17518334Speter *op++ = ((len & 3) == 3) ? IPOPT_EOL : IPOPT_NOP; 17618334Speter len++; 17718334Speter } 17818334Speter } else { 17918334Speter if (lastop != IPOPT_EOL) { 18018334Speter if (lastop == IPOPT_NOP) 18118334Speter *(op - 1) = IPOPT_EOL; 18218334Speter else { 18318334Speter *op++ = IPOPT_NOP; 18418334Speter *op++ = IPOPT_NOP; 18518334Speter *op++ = IPOPT_NOP; 18618334Speter *op = IPOPT_EOL; 18718334Speter len += 4; 18818334Speter } 18918334Speter } 19018334Speter } 19118334Speter return len; 19218334Speter} 19318334Speter