4 #include "configuration.h"
5 #include "networkInterfaces.h"
7 #include "gpsConversion.h"
19 /** The size of the buffer in which the received NMEA string is stored */
20 #define BUFFER_SIZE_FOR_OLSR 2048
22 /** The size of the buffer in which the transmit NMEA string is assembled */
23 #define BUFFER_SIZE_FROM_OLSR 512
25 /** The transmit socket address */
26 static union olsr_sockaddr * txAddress;
28 /** The de-duplication list */
29 static DeDupList deDupList;
32 Report a plugin error.
35 when true then errno is used in the error message; the error reason is also
38 a pointer to the format string
40 arguments to the format string
42 void pudError(bool useErrno, const char *format, ...) {
44 char *stringErr = NULL;
47 stringErr = strerror(errno);
50 if ((format == NULL) || (*format == '\0')) {
52 olsr_printf(0, "%s: %s\n", PUD_PLUGIN_ABBR, stringErr);
54 olsr_printf(0, "%s: Unknown error\n", PUD_PLUGIN_ABBR);
59 va_start(arglist, format);
60 vsnprintf(strDesc, sizeof(strDesc), format, arglist);
63 strDesc[sizeof(strDesc) - 1] = '\0'; /* Ensures null termination */
66 olsr_printf(0, "%s: %s: %s\n", PUD_PLUGIN_ABBR, strDesc, stringErr);
68 olsr_printf(0, "%s: %s\n", PUD_PLUGIN_ABBR, strDesc);
74 Sends a buffer out on all transmit interfaces
79 the number of bytes in the buffer
81 static void sendToAllTxInterfaces(unsigned char *buffer,
82 unsigned int bufferLength) {
83 TRxTxNetworkInterface *txNetworkInterfaces = getTxNetworkInterfaces();
84 while (txNetworkInterfaces != NULL) {
85 TRxTxNetworkInterface *networkInterface = txNetworkInterfaces;
87 #ifdef PUD_DUMP_GPS_PACKETS_TX_NON_OLSR
88 olsr_printf(0, "%s: packet sent to non-OLSR interface %s (%u bytes)\n",
89 PUD_PLUGIN_ABBR, &networkInterface->name[0], bufferLength);
90 dump_packet(&buffer[0], bufferLength);
94 if (sendto(networkInterface->socketFd, buffer, bufferLength, 0,
95 (struct sockaddr *) &txAddress->in, sizeof(txAddress->in)) < 0) {
96 pudError(true, "Transmit error on interface %s",
97 (char *) &networkInterface->name);
99 txNetworkInterfaces = networkInterface->next;
104 Called by OLSR core when a packet for the plugin is received from the OLSR
105 network. It converts the packet into an NMEA string and transmits it over all
106 transmit non-OLSR network interfaces.
109 a pointer to the received OLSR message
111 a pointer to the OLSR network interface on which the packet was received
113 a pointer to the IP address of the sender
116 - true when the packet was processed
119 bool packetReceivedFromOlsr(union olsr_message *olsrMessage,
120 struct interface *in_if __attribute__ ((unused)), union olsr_ip_addr *ipaddr __attribute__ ((unused))) {
121 const union olsr_ip_addr * originator;
122 unsigned char *olsrMessagePayload;
123 unsigned int transmitStringLength;
124 unsigned char buffer[BUFFER_SIZE_FROM_OLSR];
126 #ifdef PUD_DUMP_GPS_PACKETS_RX_OLSR
127 unsigned int olsrMessageSize;
130 /* determine the originator of the messsage */
131 if (olsr_cnf->ip_version == AF_INET) {
132 originator = (const union olsr_ip_addr *) &olsrMessage->v4.originator;
133 olsrMessagePayload = (unsigned char *) &olsrMessage->v4.message;
134 #ifdef PUD_DUMP_GPS_PACKETS_RX_OLSR
135 olsrMessageSize = ntohs(olsrMessage->v4.olsr_msgsize);
138 originator = (const union olsr_ip_addr *) &olsrMessage->v6.originator;
139 olsrMessagePayload = (unsigned char *) &olsrMessage->v6.message;
140 #ifdef PUD_DUMP_GPS_PACKETS_RX_OLSR
141 olsrMessageSize = ntohs(olsrMessage->v6.olsr_msgsize);
145 /* when we do not loopback then check if the message originated from this
147 if (!getUseLoopback() && ipequal(originator, &olsr_cnf->main_addr)) {
151 /* do deduplication: when we have already seen this message from the same
152 * originator then just back off */
153 if (likely(getUseDeDup())) {
154 if (isInDeDupList(&deDupList, olsrMessage)) {
158 addToDeDup(&deDupList, olsrMessage);
161 #ifdef PUD_DUMP_GPS_PACKETS_RX_OLSR
162 olsr_printf(0, "\n%s: packet received from OLSR interface %s (%u bytes)\n",
163 PUD_PLUGIN_ABBR, in_if->int_name, olsrMessageSize);
164 dump_packet((unsigned char *) olsrMessage, olsrMessageSize);
167 transmitStringLength = gpsFromOlsr(olsrMessage, olsrMessagePayload,
168 &buffer[0], sizeof(buffer));
169 if (unlikely(transmitStringLength == 0)) {
173 sendToAllTxInterfaces(&buffer[0], transmitStringLength);
179 Called by OLSR core when a packet for the plugin is received from the non-OLSR
180 network. It converts the packet into the internal OLSR wire format for a
181 position update and transmits it over all OLSR network interfaces.
184 the socket file descriptor on which the packet is received
186 a pointer to the network interface structure on which the packet was received
190 #ifdef PUD_DUMP_GPS_PACKETS_RX_NON_OLSR
191 static void packetReceivedForOlsr(int skfd, void *data, unsigned int flags __attribute__ ((unused))) {
193 static void packetReceivedForOlsr(int skfd, void *data __attribute__ ((unused)), unsigned int flags __attribute__ ((unused))) {
196 unsigned char rxBuffer[BUFFER_SIZE_FOR_OLSR];
198 struct sockaddr sender;
199 socklen_t senderSize = sizeof(sender);
201 assert(data != NULL);
203 /* Receive the captured Ethernet frame */
204 memset(&sender, 0, senderSize);
206 rxCount = recvfrom(skfd, &rxBuffer[0], (sizeof(rxBuffer) - 1), 0,
207 &sender, &senderSize);
209 pudError(true, "Receive error in %s, ignoring message.", __func__);
213 /* make sure the string is null-terminated */
214 rxBuffer[rxCount] = '\0';
216 /* only accept messages from configured IP addresses */
217 if (!isRxAllowedSourceIpAddress(&sender)) {
221 #ifdef PUD_DUMP_GPS_PACKETS_RX_NON_OLSR
223 TRxTxNetworkInterface * networkInterface = data;
228 if (olsr_cnf->ip_version == AF_INET) {
229 src = &((struct sockaddr_in*) &sender)->sin_addr;
230 port = ntohs(((struct sockaddr_in*) &sender)->sin_port);
232 src = &((struct sockaddr_in6*) &sender)->sin6_addr;
233 port = ntohs(((struct sockaddr_in6*) &sender)->sin6_port);
236 inet_ntop(olsr_cnf->ip_version, src, &fromAddr[0], sizeof(fromAddr));
237 olsr_printf(0, "\n%s: packet received from %s, port %u on non-OLSR"
238 " interface %s (%lu bytes)\n", PUD_PLUGIN_ABBR, &fromAddr[0],
239 port, &networkInterface->name[0], (size_t) rxCount);
241 dump_packet(&rxBuffer[0], (size_t)rxCount);
245 /* we have the received string in the rxBuffer now */
247 /* hand the NMEA information to the receiver */
248 (void) receiverUpdateGpsInformation(&rxBuffer[0], rxCount);
253 Initialise the plugin: check the configuration, initialise the NMEA parser,
254 create network interface sockets, hookup the plugin to OLSR and setup data
255 that can be setup in advance.
262 if (!checkConfig()) {
263 pudError(false, "Invalid configuration");
267 initDeDupList(&deDupList, getDeDupDepth());
269 /* set global transmit socket config */
270 txAddress = getTxMcAddr();
272 if (!startReceiver()) {
273 pudError(false, "Could not start receiver");
278 * Creates receive and transmit sockets and register the receive sockets
279 * with the OLSR stack
281 if (!createNetworkInterfaces(&packetReceivedForOlsr)) {
282 pudError(false, "Could not create require network interfaces");
286 if (!checkRunSetup()) {
287 pudError(false, "Invalid configuration");
292 * Tell OLSR to launch olsr_parser when the packets for this plugin
293 * arrive from the OLSR network
295 olsr_parser_add_function(&packetReceivedFromOlsr, PUD_OLSR_MSG_TYPE);
304 Stop the plugin: shut down all created network interface sockets and destroy
307 void closePud(void) {
308 closeNetworkInterfaces();
310 destroyDeDupList(&deDupList);