pdu.c revision 1.3 1 1.3 kefren /* $NetBSD: pdu.c,v 1.3 2013/01/28 21:35:35 kefren Exp $ */
2 1.1 kefren
3 1.1 kefren /*-
4 1.1 kefren * Copyright (c) 2010 The NetBSD Foundation, Inc.
5 1.1 kefren * All rights reserved.
6 1.1 kefren *
7 1.1 kefren * This code is derived from software contributed to The NetBSD Foundation
8 1.1 kefren * by Mihai Chelaru <kefren (at) NetBSD.org>
9 1.1 kefren *
10 1.1 kefren * Redistribution and use in source and binary forms, with or without
11 1.1 kefren * modification, are permitted provided that the following conditions
12 1.1 kefren * are met:
13 1.1 kefren * 1. Redistributions of source code must retain the above copyright
14 1.1 kefren * notice, this list of conditions and the following disclaimer.
15 1.1 kefren * 2. Redistributions in binary form must reproduce the above copyright
16 1.1 kefren * notice, this list of conditions and the following disclaimer in the
17 1.1 kefren * documentation and/or other materials provided with the distribution.
18 1.1 kefren *
19 1.1 kefren * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 1.1 kefren * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 1.1 kefren * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 1.1 kefren * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 1.1 kefren * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 1.1 kefren * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 1.1 kefren * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 1.1 kefren * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 1.1 kefren * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 1.1 kefren * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 1.1 kefren * POSSIBILITY OF SUCH DAMAGE.
30 1.1 kefren */
31 1.1 kefren
32 1.1 kefren #include <arpa/inet.h>
33 1.1 kefren
34 1.1 kefren #include <stdio.h>
35 1.1 kefren #include <strings.h>
36 1.1 kefren #include <stdlib.h>
37 1.1 kefren
38 1.1 kefren #include "socketops.h"
39 1.1 kefren #include "ldp_errors.h"
40 1.1 kefren #include "ldp.h"
41 1.1 kefren #include "ldp_peer.h"
42 1.1 kefren #include "notifications.h"
43 1.1 kefren #include "pdu.h"
44 1.1 kefren
45 1.1 kefren uint
46 1.1 kefren get_pdu(unsigned char *s, struct ldp_pdu * p)
47 1.1 kefren {
48 1.1 kefren struct ldp_pdu *p1;
49 1.1 kefren p1 = (struct ldp_pdu *) s;
50 1.1 kefren
51 1.1 kefren p->version = ntohs(p1->version);
52 1.1 kefren p->length = ntohs(p1->length);
53 1.1 kefren memcpy(&p->ldp_id, &p1->ldp_id, sizeof(struct in_addr));
54 1.1 kefren p->label_space = ntohs(p1->label_space);
55 1.1 kefren
56 1.1 kefren return MIN_PDU_SIZE;
57 1.1 kefren }
58 1.1 kefren
59 1.1 kefren /* Checks an incoming PDU for size and version */
60 1.1 kefren int
61 1.1 kefren check_recv_pdu(struct ldp_peer * p, struct ldp_pdu * rpdu, int c)
62 1.1 kefren {
63 1.1 kefren struct notification_tlv *notiftlv;
64 1.1 kefren
65 1.1 kefren /* Avoid underflow */
66 1.1 kefren if (c < MIN_PDU_SIZE)
67 1.1 kefren return LDP_E_BAD_LENGTH;
68 1.1 kefren
69 1.3 kefren if (p->ldp_id.s_addr != rpdu->ldp_id.s_addr) {
70 1.3 kefren fatalp("Invalid LDP ID received from %s\n",
71 1.3 kefren inet_ntoa(p->ldp_id));
72 1.3 kefren notiftlv = build_notification(0,
73 1.3 kefren NOTIF_FATAL | NOTIF_BAD_LDP_ID);
74 1.3 kefren send_tlv(p, (struct tlv *) notiftlv);
75 1.3 kefren free(notiftlv);
76 1.3 kefren return LDP_E_BAD_ID;
77 1.3 kefren }
78 1.1 kefren
79 1.1 kefren /* Check PDU for right LDP version */
80 1.1 kefren if (ntohs(rpdu->version) != LDP_VERSION) {
81 1.1 kefren fatalp("Invalid PDU version received from %s (%d)\n",
82 1.2 kefren satos(p->address), ntohs(rpdu->version));
83 1.3 kefren notiftlv = build_notification(0,
84 1.3 kefren NOTIF_FATAL | NOTIF_BAD_LDP_VER);
85 1.1 kefren send_tlv(p, (struct tlv *) notiftlv);
86 1.1 kefren free(notiftlv);
87 1.1 kefren return LDP_E_BAD_VERSION;
88 1.1 kefren }
89 1.1 kefren /* Check PDU for length validity */
90 1.1 kefren if (ntohs(rpdu->length) > c - PDU_VER_LENGTH) {
91 1.1 kefren fatalp("Invalid PDU length received from %s (announced %d, "
92 1.2 kefren "received %d)\n", satos(p->address),
93 1.1 kefren ntohs(rpdu->length), (int) (c - PDU_VER_LENGTH));
94 1.3 kefren notiftlv = build_notification(0,
95 1.3 kefren NOTIF_FATAL | NOTIF_BAD_PDU_LEN);
96 1.1 kefren send_tlv(p, (struct tlv *) notiftlv);
97 1.1 kefren free(notiftlv);
98 1.1 kefren return LDP_E_BAD_LENGTH;
99 1.1 kefren }
100 1.1 kefren return LDP_E_OK;
101 1.1 kefren }
102