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