1/*	$OpenBSD: l2tp_subr.h,v 1.6 2013/09/20 07:26:23 yasuoka Exp $	*/
2
3/*-
4 * Copyright (c) 2009 Internet Initiative Japan Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28#ifndef	L2TP_SUBR_H
29#define	L2TP_SUBR_H	1
30/* $Id: l2tp_subr.h,v 1.6 2013/09/20 07:26:23 yasuoka Exp $ */
31
32/**
33 * structure of L2TP Attribute Value Pair (AVP) packet header
34 */
35struct l2tp_avp
36{
37#if	BYTE_ORDER == LITTLE_ENDIAN
38	uint16_t	length:10,
39			rsvd:4,
40			is_hidden:1,
41			is_mandatory:1;
42#else
43	uint16_t	is_mandatory:1,
44			is_hidden:1,
45			rsvd:4,
46			length:10;
47#endif
48	uint16_t	vendor_id;
49	uint16_t	attr_type;
50	u_char 		attr_value[0];
51} __attribute__((__packed__)) ;
52
53#define	avp_attr_length(avp)	((avp)->length - 6)
54
55static inline uint16_t
56avp_get_val16(struct l2tp_avp *avp)
57{
58	return (avp->attr_value[0] << 8) | avp->attr_value[1];
59}
60static inline uint32_t
61avp_get_val32(struct l2tp_avp *avp)
62{
63	return (avp->attr_value[0] << 24) | (avp->attr_value[1] << 16) |
64		(avp->attr_value[2] << 8) | avp->attr_value[3];
65}
66
67static inline void
68avp_set_val16(struct l2tp_avp *avp, uint16_t val)
69{
70	avp->attr_value[0] = val >> 8;
71	avp->attr_value[1] = val & 0xff;
72}
73
74static inline void
75avp_set_val32(struct l2tp_avp *avp, uint32_t val)
76{
77	avp->attr_value[0] = val >> 24;
78	avp->attr_value[1] = val >> 16;
79	avp->attr_value[2] = val >> 8;
80	avp->attr_value[3] = val & 0xff;
81}
82
83static inline int
84short_cmp(const void *m, const void *n)
85{
86	return ((intptr_t)m - (intptr_t)n);
87}
88
89static inline uint32_t
90short_hash(const void *v, int sz)
91{
92	return ((uintptr_t)v % sz);
93}
94
95/*
96 * macro to check AVP size.
97 * Prepare 1) char array `emes' for error message, 2) size_check_failed label
98 * before use this macro.
99 */
100#define	AVP_SIZE_CHECK(_avp, _op, _exp)					\
101	do {								\
102		if (!((_avp)->length _op (_exp))) {			\
103			snprintf(emes, sizeof(emes),			\
104			    "invalid packet size %s %d" #_op "%d)",	\
105			    avp_attr_type_string((_avp)->attr_type),	\
106			    (_avp)->length, (_exp));			\
107			goto size_check_failed;				\
108		}							\
109	} while (/* CONSTCOND */0)
110#define AVP_MAXLEN_CHECK(_avp, _maxlen)					\
111	do {								\
112		if ((_avp)->length > (_maxlen) + 6) {			\
113			snprintf(emes, sizeof(emes),			\
114			    "Attribute value is too long %s %d > %d",	\
115			    avp_attr_type_string((_avp)->attr_type),	\
116			    (_avp)->length - 6, (int)(_maxlen));	\
117			goto size_check_failed;				\
118		}							\
119	} while (/* CONSTCOND */0)
120
121#ifdef __cplusplus
122extern "C" {
123#endif
124
125int              avp_enum (struct l2tp_avp *, const u_char *, int, int);
126const char       *avp_attr_type_string (int);
127struct l2tp_avp  *avp_find_message_type_avp(struct l2tp_avp *, const u_char *, int);
128struct l2tp_avp  *avp_find(struct l2tp_avp *, const u_char *, int, uint16_t, uint16_t, int);
129int              bytebuf_add_avp (bytebuffer *, struct l2tp_avp *, int);
130const char       *avp_mes_type_string (int);
131const char *     l2tp_cdn_rcode_string(int);
132const char *     l2tp_stopccn_rcode_string(int);
133const char *     l2tp_ecode_string(int);
134
135#ifdef __cplusplus
136}
137#endif
138
139#endif
140