5 #include "networkInterfaces.h"
6 #include "configuration.h"
7 #include "gpsConversion.h"
21 /** The size of the buffer in which the received NMEA string is stored */
22 #define BUFFER_SIZE_RX_NMEA 2048
24 /** The size of the buffer in which the received downlink message is stored */
25 #define BUFFER_SIZE_RX_DOWNLINK 2048
27 /** The size of the buffer in which the converted NMEA string is assembled for
28 * transmission over OSLR */
29 #define BUFFER_SIZE_TX_OLSR 512
31 /** The de-duplication list */
32 static DeDupList deDupList;
34 /** When false, use olsr_printf in pudError, otherwise use olsr_syslog */
35 static bool pudErrorUseSysLog = false;
38 Report a plugin error.
41 when true then errno is used in the error message; the error reason is also
44 a pointer to the format string
46 arguments to the format string
48 void pudError(bool useErrno, const char *format, ...) {
51 const char *stringErr;
53 if ((format == NULL) || (*format == '\0')) {
57 stringErr = "Unknown error";
59 stringErr = strerror(errno);
64 va_start(arglist, format);
65 vsnprintf(strDesc, sizeof(strDesc), format, arglist);
70 stringErr = strerror(errno);
77 if (!pudErrorUseSysLog)
78 olsr_printf(0, "%s: %s%s%s\n", PUD_PLUGIN_ABBR, strDesc, colon, stringErr);
80 olsr_syslog(OLSR_LOG_ERR, "%s: %s%s%s\n", PUD_PLUGIN_ABBR, strDesc, colon, stringErr);
84 Sends a buffer out on all transmit interfaces
89 the number of bytes in the buffer
91 static void sendToAllTxInterfaces(unsigned char *buffer,
92 unsigned int bufferLength) {
93 union olsr_sockaddr * txAddress = getTxMcAddr();
96 TRxTxNetworkInterface *txNetworkInterfaces = getTxNetworkInterfaces();
98 if (txAddress->in.sa_family == AF_INET) {
99 addr = &txAddress->in4;
100 addrSize = sizeof(struct sockaddr_in);
102 addr = &txAddress->in6;
103 addrSize = sizeof(struct sockaddr_in6);
106 while (txNetworkInterfaces != NULL) {
107 TRxTxNetworkInterface *networkInterface = txNetworkInterfaces;
109 if (sendto(networkInterface->socketFd, buffer, bufferLength, 0, addr, addrSize) < 0) {
110 pudError(true, "Transmit error on interface %s", &networkInterface->name[0]);
112 txNetworkInterfaces = networkInterface->next;
117 Called by OLSR core when a packet for the plugin is received from the OLSR
118 network. It converts the packet into an NMEA string and transmits it over all
119 transmit non-OLSR network interfaces.
122 a pointer to the received OLSR message
124 a pointer to the OLSR network interface on which the packet was received
126 a pointer to the IP address of the sender
129 - true when the packet was processed
132 bool packetReceivedFromOlsr(union olsr_message *olsrMessage,
133 struct interface *in_if __attribute__ ((unused)), union olsr_ip_addr *ipaddr __attribute__ ((unused))) {
134 const union olsr_ip_addr * originator = getOlsrMessageOriginator(
135 olsr_cnf->ip_version, olsrMessage);
136 unsigned int transmitStringLength;
137 unsigned char buffer[BUFFER_SIZE_TX_OLSR];
139 /* when we do not loopback then check if the message originated from this
141 if (!getUseLoopback() && ipequal(originator, &olsr_cnf->main_addr)) {
145 /* do deduplication: when we have already seen this message from the same
146 * originator then just back off */
147 if (likely(getUseDeDup())) {
148 if (isInDeDupList(&deDupList, olsrMessage)) {
152 addToDeDup(&deDupList, olsrMessage);
155 transmitStringLength = gpsFromOlsr(olsrMessage, &buffer[0], sizeof(buffer));
156 if (unlikely(transmitStringLength == 0)) {
160 sendToAllTxInterfaces(&buffer[0], transmitStringLength);
166 Called by OLSR core when a packet for the plugin is received from the downlink.
167 It unpacks the messages and distributes them into OLSR and on the LAN.
170 the socket file descriptor on which the packet is received
172 a pointer to the network interface structure on which the packet was received
176 static void packetReceivedFromDownlink(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused))) {
178 unsigned char rxBuffer[BUFFER_SIZE_RX_DOWNLINK];
182 /* Receive the captured Ethernet frame */
184 rxCount = recvfrom(skfd, &rxBuffer[0], (sizeof(rxBuffer) - 1), 0, NULL, NULL);
186 pudError(true, "Receive error in %s, ignoring message.", __func__);
190 while (rxIndex < rxCount) {
191 UplinkMessage * msg = (UplinkMessage *) &rxBuffer[rxIndex];
193 uint16_t uplinkMessageLength;
194 uint16_t olsrMessageLength;
196 union olsr_message * olsrMessage;
198 type = getUplinkMessageType(&msg->header);
199 olsrMessageLength = getUplinkMessageLength(&msg->header);
200 uplinkMessageLength = olsrMessageLength + sizeof(UplinkHeader);
202 if (unlikely((rxIndex + uplinkMessageLength) > rxCount)) {
203 pudError(false, "Received wrong length (%d) in %s,"
204 " ignoring the rest of the messages.", olsrMessageLength,
209 rxIndex += uplinkMessageLength;
211 if (type != POSITION) {
212 pudError(false, "Received wrong type (%d) in %s,"
213 " ignoring message.", type, __func__);
217 ipv6 = getUplinkMessageIPv6(&msg->header);
218 if (unlikely(ipv6 && (olsr_cnf->ip_version != AF_INET6))) {
219 pudError(false, "Received wrong IPv6 status (%s) in %s,"
220 " ignoring message.", (ipv6 ? "true" : "false"),
225 olsrMessage = &msg->msg.olsrMessage;
227 /* we now have a position update (olsrMessage) of a certain length
228 * (olsrMessageLength). this needs to be transmitted over OLSR and on the LAN */
230 /* send out over OLSR interfaces */
233 struct interface *ifn;
234 for (ifn = ifnet; ifn; ifn = ifn->int_next) {
235 r = net_outbuffer_push(ifn, olsrMessage, olsrMessageLength);
236 if (r != (int) olsrMessageLength) {
239 "Could not send to OLSR interface %s: %s"
240 " (length=%u, r=%d)",
242 ((r == -1) ? "no buffer was found" :
243 (r == 0) ? "there was not enough room in the buffer" :
244 "unknown reason"), olsrMessageLength, r);
249 /* send out over tx interfaces */
250 (void) packetReceivedFromOlsr(olsrMessage, NULL, NULL);
256 Called by OLSR core when a packet for the plugin is received from the non-OLSR
257 network. It converts the packet into the internal OLSR wire format for a
258 position update and transmits it over all OLSR network interfaces.
261 the socket file descriptor on which the packet is received
263 a pointer to the network interface structure on which the packet was received
267 static void packetReceivedForOlsr(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused))) {
269 unsigned char rxBuffer[BUFFER_SIZE_RX_NMEA];
271 union olsr_sockaddr sender;
272 socklen_t senderSize = sizeof(sender);
274 assert(data != NULL);
276 /* Receive the captured Ethernet frame */
277 memset(&sender, 0, senderSize);
279 rxCount = recvfrom(skfd, &rxBuffer[0], (sizeof(rxBuffer) - 1), 0,
280 (struct sockaddr *)&sender, &senderSize);
282 pudError(true, "Receive error in %s, ignoring message.", __func__);
286 /* make sure the string is null-terminated */
287 rxBuffer[rxCount] = '\0';
289 /* only accept messages from configured IP addresses */
290 if (!isRxAllowedSourceIpAddress(&sender)) {
294 /* we have the received string in the rxBuffer now */
296 /* hand the NMEA information to the receiver */
297 (void) receiverUpdateGpsInformation(&rxBuffer[0], rxCount);
302 Initialise the plugin: check the configuration, initialise the NMEA parser,
303 create network interface sockets, hookup the plugin to OLSR and setup data
304 that can be setup in advance.
311 if (!checkConfig()) {
312 pudError(false, "Invalid configuration");
318 if (!initDeDupList(&deDupList, getDeDupDepth())) {
319 pudError(false, "Could not initialise de-duplication list");
323 if (!startReceiver()) {
324 pudError(false, "Could not start receiver");
329 * Creates receive and transmit sockets and register the receive sockets
330 * with the OLSR stack
332 if (!createNetworkInterfaces(&packetReceivedForOlsr,
333 &packetReceivedFromDownlink)) {
334 pudError(false, "Could not create require network interfaces");
338 if (!checkRunSetup()) {
339 pudError(false, "Invalid configuration");
344 * Tell OLSR to call packetReceivedFromOlsr when the packets for this
345 * plugin arrive from the OLSR network
347 olsr_parser_add_function(&packetReceivedFromOlsr, PUD_OLSR_MSG_TYPE);
349 /* switch to syslog logging, load was succesful */
350 pudErrorUseSysLog = !olsr_cnf->no_fork;
359 Stop the plugin: shut down all created network interface sockets and destroy
362 void closePud(void) {
363 closeNetworkInterfaces();
365 destroyDeDupList(&deDupList);