blob: 6e1faf5d8d777fc71ec461cbc76b01af5d2187e6 [file] [log] [blame]
Pablo Neira Ayuso95306002012-08-22 16:43:59 +02001/* (C) 2008-2012 by Harald Welte <laforge@gnumonks.org>
2 *
3 * All Rights Reserved
4 *
5 * Author: Harald Welte <laforge@gnumonks.org>
6 * Pablo Neira Ayuso <pablo@gnumonks.org>
7 *
Harald Welte323d39d2017-11-13 01:09:21 +09008 * SPDX-License-Identifier: AGPL-3.0+
9 *
Pablo Neira Ayuso95306002012-08-22 16:43:59 +020010 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU Affero General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Affero General Public License for more details.
19 *
20 * You should have received a copy of the GNU Affero General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
22 *
23 */
24
25#include <stdio.h>
26#include <stdint.h>
27#include <stddef.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <fcntl.h>
31#include <unistd.h>
32#include <sys/time.h>
33#include <arpa/inet.h>
34#include <string.h>
35#include <errno.h>
36
37#include <osmocom/core/msgb.h>
38#include <osmocom/core/logging.h>
39#include <osmocom/core/utils.h>
40
41#include <osmocom/abis/lapd_pcap.h>
42
43/*
44 * pcap writing of the mlapd load
45 * pcap format is from http://wiki.wireshark.org/Development/LibpcapFileFormat
46 */
47#define DLT_LINUX_LAPD 177
Harald Welteb4698ef2016-07-04 09:55:26 +020048#define LINUX_SLL_HOST 0
49#define LINUX_SLL_OUTGOING 4
Pablo Neira Ayuso95306002012-08-22 16:43:59 +020050
51struct pcap_hdr {
52 uint32_t magic_number;
53 uint16_t version_major;
54 uint16_t version_minor;
55 int32_t thiszone;
56 uint32_t sigfigs;
57 uint32_t snaplen;
58 uint32_t network;
59} __attribute__((packed));
60
61struct pcap_rechdr {
62 uint32_t ts_sec;
63 uint32_t ts_usec;
64 uint32_t incl_len;
65 uint32_t orig_len;
66} __attribute__((packed));
67
68struct pcap_lapdhdr {
69 uint16_t pkttype;
70 uint16_t hatype;
71 uint16_t halen;
Harald Welteb4698ef2016-07-04 09:55:26 +020072 uint8_t addr[8];
Pablo Neira Ayuso95306002012-08-22 16:43:59 +020073 int16_t protocol;
74} __attribute__((packed));
75
76osmo_static_assert(offsetof(struct pcap_lapdhdr, hatype) == 2, hatype_offset);
77osmo_static_assert(offsetof(struct pcap_lapdhdr, halen) == 4, halen_offset);
78osmo_static_assert(offsetof(struct pcap_lapdhdr, addr) == 6, addr_offset);
79osmo_static_assert(offsetof(struct pcap_lapdhdr, protocol) == 14, proto_offset);
80osmo_static_assert(sizeof(struct pcap_lapdhdr) == 16, lapd_header_size);
81
Harald Welte47bee5b2016-07-04 09:53:44 +020082int osmo_pcap_lapd_set_fd(int fd)
Pablo Neira Ayuso95306002012-08-22 16:43:59 +020083{
Harald Welte47bee5b2016-07-04 09:53:44 +020084 struct pcap_hdr pcap_header = {
Pablo Neira Ayuso95306002012-08-22 16:43:59 +020085 .magic_number = 0xa1b2c3d4,
86 .version_major = 2,
87 .version_minor = 4,
88 .thiszone = 0,
89 .sigfigs = 0,
90 .snaplen = 65535,
91 .network = DLT_LINUX_LAPD,
92 };
93
Harald Welte47bee5b2016-07-04 09:53:44 +020094 if (write(fd, &pcap_header, sizeof(pcap_header))
95 != sizeof(pcap_header)) {
96 LOGP(DLLAPD, LOGL_ERROR, "cannot write PCAP header: %s\n",
97 strerror(errno));
98 close(fd);
99 return -1;
100 }
101
102 return 0;
103}
104
105int osmo_pcap_lapd_open(char *filename, mode_t mode)
106{
107 int fd, rc;
108
Pablo Neira Ayuso95306002012-08-22 16:43:59 +0200109 LOGP(DLLAPD, LOGL_NOTICE, "opening LAPD pcap file `%s'\n", filename);
110
111 fd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, mode);
112 if (fd < 0) {
113 LOGP(DLLAPD, LOGL_ERROR, "failed to open PCAP file: %s\n",
114 strerror(errno));
115 return -1;
116 }
Harald Welte47bee5b2016-07-04 09:53:44 +0200117
118 rc = osmo_pcap_lapd_set_fd(fd);
119 if (rc < 0) {
Pablo Neira Ayuso95306002012-08-22 16:43:59 +0200120 close(fd);
Harald Welte47bee5b2016-07-04 09:53:44 +0200121 return rc;
Pablo Neira Ayuso95306002012-08-22 16:43:59 +0200122 }
Harald Welte47bee5b2016-07-04 09:53:44 +0200123
Pablo Neira Ayuso95306002012-08-22 16:43:59 +0200124 return fd;
125}
126
127/* This currently only works for the D-Channel */
128int osmo_pcap_lapd_write(int fd, int direction, struct msgb *msg)
129{
Pablo Neira Ayuso95306002012-08-22 16:43:59 +0200130 struct timeval tv;
Harald Weltedcbc00d2022-06-27 08:06:25 +0200131 struct {
132 struct pcap_rechdr pcap_rechdr;
133 struct pcap_lapdhdr header;
134 char buf[msg->len];
135 } __attribute__((packed)) s;
Pablo Neira Ayuso95306002012-08-22 16:43:59 +0200136
137 /* PCAP file has not been opened, skip. */
138 if (fd < 0)
139 return 0;
140
Harald Weltedcbc00d2022-06-27 08:06:25 +0200141 memset(&s, 0, sizeof(s));
142
143 s.pcap_rechdr.ts_sec = 0;
144 s.pcap_rechdr.ts_usec = 0;
145 s.pcap_rechdr.incl_len = msg->len + sizeof(struct pcap_lapdhdr);
146 s.pcap_rechdr.orig_len = msg->len + sizeof(struct pcap_lapdhdr);
Pablo Neira Ayuso95306002012-08-22 16:43:59 +0200147
Harald Welteb4698ef2016-07-04 09:55:26 +0200148 if (direction == OSMO_LAPD_PCAP_OUTPUT)
Harald Weltedcbc00d2022-06-27 08:06:25 +0200149 s.header.pkttype = htons(LINUX_SLL_OUTGOING);
Harald Welteb4698ef2016-07-04 09:55:26 +0200150 else
Harald Weltedcbc00d2022-06-27 08:06:25 +0200151 s.header.pkttype = htons(LINUX_SLL_HOST);
152 s.header.hatype = 0;
153 s.header.halen = 0;
154 s.header.addr[0] = 0x01; /* we are the network side */
155 s.header.protocol = ntohs(48);
Pablo Neira Ayuso95306002012-08-22 16:43:59 +0200156
157 gettimeofday(&tv, NULL);
Harald Weltedcbc00d2022-06-27 08:06:25 +0200158 s.pcap_rechdr.ts_sec = tv.tv_sec;
159 s.pcap_rechdr.ts_usec = tv.tv_usec;
Pablo Neira Ayuso95306002012-08-22 16:43:59 +0200160
Harald Weltedcbc00d2022-06-27 08:06:25 +0200161 memcpy(s.buf, msg->data, msg->len);
Pablo Neira Ayuso95306002012-08-22 16:43:59 +0200162
Harald Weltedcbc00d2022-06-27 08:06:25 +0200163 if (write(fd, &s, sizeof(s)) != sizeof(s)) {
Pablo Neira Ayuso95306002012-08-22 16:43:59 +0200164 LOGP(DLLAPD, LOGL_ERROR, "cannot write packet to PCAP: %s\n",
165 strerror(errno));
166 return -1;
167 }
Harald Weltedcbc00d2022-06-27 08:06:25 +0200168 return sizeof(s);
Pablo Neira Ayuso95306002012-08-22 16:43:59 +0200169}
170
171int osmo_pcap_lapd_close(int fd)
172{
173 LOGP(DLLAPD, LOGL_NOTICE, "closing LAPD pcap file\n");
174 return close(fd);
175}