1 /*******************************************************************************
2 * input_vlan.c: vlan input method
4 *******************************************************************************
6 *******************************************************************************/
8 /* ???????????????????????????????????????????????????????????????????????????
9 * This works (well, it should :), but should have a good place in horror museum:
10 * - the vlan-capable interfaces are retrieved from a names list, instead
11 * of being read from the system
12 * - the vlan server sucks, and therefore the vlan clients sucks:
13 * - it is unable to process several operations between a login and a logout
14 * A lot of requests could be grouped if it could.
15 * - it is incoherent concerning it's messages (and what it needs to perform
17 * - it is totally unable to handle several mac adresses on a single switch
18 * port (and therefore bridged/hubbed machines)
19 * - however, the API is ok, should be able to handle all futures evolutions,
20 * including vlan-conscient cards.
22 * So there is a lot to do in this file, but not before having reprogrammed the
24 * What would be a good interface to the vlan server ? Here are some ideas:
26 * ??????????????????????????????????????????????????????????????????????????? */
28 /*******************************************************************************
30 *******************************************************************************/
40 #include <arpa/inet.h>
42 #include <netinet/in.h>
43 #include <sys/ioctl.h>
44 #include <sys/soundcard.h>
47 #include <X11/extensions/XShm.h>
52 #include "vlc_thread.h"
56 #include "input_vlan.h"
58 #include "audio_output.h"
61 #include "video_output.h"
64 #include "interface.h"
67 #include "pgm_data.h"*/
69 /*******************************************************************************
70 * input_vlan_iface_t: vlan-capable network interface
71 *******************************************************************************
72 * This structure describes the abilities of a network interface capable of
73 * vlan management. Note that an interface could have several IP adresses, but
74 * since only the MAC address is used to change vlan, only one needs to be
76 * ?? it could be interesting to send a port id on vlan request, to know if two
77 * interfaces are dependant regarding vlan changes.
78 *******************************************************************************/
81 char * psz_name; /* interface name */
82 struct sockaddr_in sa_in; /* interface IP */
83 char psz_mac[20]; /* interface MAC */
85 /* Hardware properties */
86 int i_master; /* master interface index */
87 int i_switch; /* switch number */
88 int i_port; /* port number */
89 int i_sharers; /* number of MACs on this port */
91 /* Vlan properties - these are only used if i_master is negative */
92 int i_refcount; /* locks counter */
93 int i_vlan; /* current vlan */
94 int i_default_vlan; /* default vlan */
97 /*******************************************************************************
98 * input_vlan_server_t: vlan server
99 *******************************************************************************
100 * This structure describes a vlan server.
101 *******************************************************************************/
104 struct sockaddr_in sa_in; /* server address */
105 int i_socket; /* socket descriptor */
107 /* Login informations */
108 char * psz_login; /* server login */
109 char * psz_passwd; /* server password */
110 } input_vlan_server_t;
112 /*******************************************************************************
114 *******************************************************************************
115 * Store global vlan library data.
116 *******************************************************************************/
117 typedef struct input_vlan_method_s
119 vlc_mutex_t lock; /* library lock */
122 input_vlan_server_t server; /* vlan server */
124 /* Network interfaces */
125 int i_ifaces; /* number of vlan-compliant interfaces */
126 input_vlan_iface_t * p_iface; /* interfaces */
127 } input_vlan_method_t;
133 /* List of vlan-capable interfaces names */
134 static const char *psz_ifaces_names[] = { "eth0", "eth1", "eth2", "eth3", "eth4", "eth5", NULL };
139 static int IfaceInfo ( input_vlan_iface_t *p_iface );
140 static int IfaceDependance ( input_vlan_method_t *p_method, int i_iface );
141 static int ServerLogin ( input_vlan_server_t *p_server );
142 static void ServerLogout ( input_vlan_server_t *p_server );
143 static int ServerRequestChange ( input_vlan_server_t *p_server,
144 input_vlan_iface_t *p_iface, int i_vlan );
145 static int ServerRequestInfo ( input_vlan_server_t *p_server,
146 input_vlan_iface_t *p_iface );
148 /*******************************************************************************
149 * input_VlanCreate: initialize global vlan method data
150 *******************************************************************************
151 * Initialize vlan input method global data. This function should be called
152 * once before any input thread is created or any call to other input_Vlan*()
153 * function is attempted.
154 *******************************************************************************/
155 int input_VlanCreate( void )
157 char * psz_server; // ??? get from environment
158 int i_port; // ??? get from environment
159 int i_index; /* interface/servers index */
160 input_vlan_iface_t * p_iface; /* interfaces */
161 input_vlan_method_t *p_method = p_main->p_input_vlan; //??
163 /* Build vlan server descriptor */
164 if( BuildInetAddr( &p_method->server.sa_in, psz_server, i_port ) )
169 /* Allocate interfaces array */
170 for( i_index = 0; psz_ifaces_names[i_index] != NULL; i_index++ )
174 p_iface = malloc( sizeof(input_vlan_iface_t) * i_index );
175 if( p_iface == NULL )
180 /* Initialize interfaces array */
181 for( i_index = p_method->i_ifaces = 0; psz_ifaces_names[i_index] != NULL; i_index++ )
183 /* Retrieve interface name */
184 p_iface[p_method->i_ifaces].psz_name = (char *) psz_ifaces_names[i_index];
186 /* Test if interface is vlan-capable */
187 if( !IfaceInfo( &p_iface[p_method->i_ifaces] ) )
189 /* If interface passed first step, login to vlan server */
190 if( !ServerLogin( &p_method->server ) )
192 /* Request informations from server about the interface - if the interface
193 * pass this last test, it is vlan-capable and can be added to the list of
195 if( !ServerRequestInfo( &p_method->server, &p_iface[p_method->i_ifaces]) )
197 /* Check if interface is dependant */
198 if( !IfaceDependance( p_method, p_method->i_ifaces ) )
200 /* Interface is master: initialize properties */
201 p_iface[p_method->i_ifaces].i_default_vlan = p_iface[p_method->i_ifaces].i_vlan;
202 p_iface[p_method->i_ifaces].i_refcount = 0;
203 intf_DbgMsg("input debug: added vlan-capable interface %s (%s)\n",
204 p_iface[p_method->i_ifaces].psz_name,
205 p_iface[p_method->i_ifaces].psz_mac);
210 /* Interface is slave */
211 intf_DbgMsg("input debug: added vlan-capable interface %s (%s), depends from %s\n",
212 p_iface[p_method->i_ifaces].psz_name,
213 p_iface[p_method->i_ifaces].psz_mac,
214 p_iface[p_iface[p_method->i_ifaces].i_master].psz_name );
217 /* Increment size counter */
218 p_method->i_ifaces++;
220 /* Logout from server */
221 ServerLogout( &p_method->server );
226 /* If number of vlan-capable interfaces is null, then desactivate vlans */
227 if( p_method->i_ifaces == 0 )
233 /* Reallocate interfaces array to save memory */
234 p_method->p_iface = realloc( p_iface, sizeof(input_vlan_iface_t) * p_method->i_ifaces );
235 if( p_method->p_iface == NULL )
237 /* Realloc failed, but the previous pointer is still valid */
238 p_method->p_iface = p_iface;
241 /* Initialize lock */
242 vlc_mutex_init( &p_method->lock );
244 intf_Msg("input: vlans input method installed\n", p_method->i_ifaces);
248 /*******************************************************************************
249 * input_VlanDestroy: free global vlan method data
250 *******************************************************************************
251 * Free resources allocated by input_VlanMethodInit. This function should be
252 * called at the end of the program.
253 *******************************************************************************/
254 void input_VlanDestroy( void )
256 int i_index; /* server/interface index */
257 input_vlan_method_t *p_method = p_main->p_input_vlan; // ??
259 /* Leave all remaining vlans */
260 for( i_index = 0; i_index < p_method->i_ifaces; i_index++ )
263 /* Check if interface is still locked */
264 if( p_method->p_iface[i_index].i_refcount )
266 intf_DbgMsg("input debug: interface %s is still vlan-locked\n",
267 p_method->p_iface[i_index].psz_name);
268 p_method->p_iface[i_index].i_refcount = 0;
271 /* Join default (starting) vlan */
272 input_VlanJoin( VLAN_ID( i_index, p_method->p_iface[i_index].i_default_vlan ) );
275 /* Free interfaces array */
276 free( p_method->p_iface );
278 intf_DbgMsg("input debug: vlan method terminated\n");
281 /*******************************************************************************
282 * input_VlanId: get a vlan_id for a given interface
283 *******************************************************************************
284 * Get a vlan_id given a network interface and a vlan number. If psz_iface is
285 * NULL, then the default network interface will be used. A negative value
286 * will be returned in case of error.
287 *******************************************************************************/
288 int input_VlanId( char *psz_iface, int i_vlan )
290 input_vlan_method_t * p_method; /* method global data */
291 int i_index; /* interface index */
293 p_method = p_main->p_input_vlan;
295 /* If psz_iface is NULL, use first (default) interface (if there is one) */
296 if( psz_iface == NULL )
298 return( p_method->i_ifaces ? VLAN_ID( 0, i_vlan ) : -1 );
301 /* Browse all interfaces */
302 for( i_index = 0; i_index < p_main->p_input_vlan->i_ifaces ; i_index++ )
304 /* If interface has been found, return */
305 if( !strcmp( p_main->p_input_vlan->p_iface[i_index].psz_name, psz_iface ) )
307 return( VLAN_ID( i_index, i_vlan ) );
314 /*******************************************************************************
315 * input_VlanJoin: join a vlan
316 *******************************************************************************
317 * This function will try to join a vlan. If the relevant interface is already
318 * on the good vlan, nothing will be done. Else, and if possible (if the
319 * interface is not locked), the vlan server will be contacted and a change will
320 * be requested. The function will block until the change is effective. Note
321 * that once a vlan is no more used, it's interface should be unlocked using
323 * Non 0 will be returned in case of error.
324 *******************************************************************************/
325 int input_VlanJoin( int i_vlan_id )
327 input_vlan_method_t * p_method; /* method global data */
328 input_vlan_iface_t * p_iface; /* interface (shortcut) */
329 int i_err; /* error indicator */
331 /* Initialize shortcuts, and use master if interface is dependant */
333 p_method = p_main->p_input_vlan;
334 p_iface = &p_method->p_iface[ VLAN_ID_IFACE( i_vlan_id ) ];
335 if( p_iface->i_master >= 0 )
337 p_iface = &p_method->p_iface[ p_iface->i_master ];
341 vlc_mutex_lock( &p_method->lock );
343 /* If the interface is in the wished vlan, increase lock counter */
344 if( p_iface->i_vlan != VLAN_ID_VLAN( i_vlan_id ) )
346 p_iface->i_refcount++;
348 /* If not, if it is not locked, the vlan can be changed */
349 else if( !p_iface->i_refcount )
351 /* Login to server */
352 if( (i_err = !ServerLogin( &p_method->server )) )
355 /* Request vlan change */
356 if( (i_err = !ServerRequestChange( &p_method->server,
357 p_iface, VLAN_ID_VLAN( i_vlan_id ) ) ) )
359 p_iface->i_refcount++;
362 ServerLogout( &p_method->server );
365 /* Else, the vlan is locked and can't be changed */
371 /* Release lock (if this point is reached, the function succeeded) */
372 vlc_mutex_unlock( &p_method->lock );
376 /*******************************************************************************
377 * input_VlanLeave: leave a vlan
378 *******************************************************************************
379 * This function tells the vlan library that the designed interface is no more
380 * locked and than vlan changes can occur.
381 *******************************************************************************/
382 void input_VlanLeave( int i_vlan_id )
384 input_vlan_method_t * p_method; /* method global data */
385 input_vlan_iface_t * p_iface; /* interface (shortcut) */
386 int i_err; /* error indicator */
388 /* Initialize shortcuts, and use master if interface is dependant */
390 p_method = p_main->p_input_vlan;
391 p_iface = &p_method->p_iface[ VLAN_ID_IFACE( i_vlan_id ) ];
392 if( p_iface->i_master >= 0 )
394 p_iface = &p_method->p_iface[ p_iface->i_master ];
398 vlc_mutex_lock( &p_method->lock );
400 /* Decrease reference counter */
401 p_method->p_iface[ VLAN_ID_IFACE( i_vlan_id ) ].i_refcount--;
404 vlc_mutex_unlock( &p_method->lock );
407 /*******************************************************************************
408 * input_VlanRequest: request vlan number for a given interface
409 *******************************************************************************
410 * Request the vlan number (and not id) of a given network interface. A
411 * connection to the server can eventually occur, event if it not the case in
412 * current implementation. A negative number can be returned on error.
413 *******************************************************************************/
414 int input_VlanRequest( char *psz_iface )
416 input_vlan_method_t * p_method; /* method global data */
417 int i_index; /* interface index */
419 p_method = p_main->p_input_vlan;
421 /* If psz_iface is NULL, use first (default) interface (if there is one) -
422 * note that interface 0 can't be dependant, so dependance does not need
424 if( psz_iface == NULL )
426 return( p_method->i_ifaces ? p_method->p_iface[0].i_vlan : -1 );
429 /* Browse all interfaces */
430 for( i_index = 0; i_index < p_method->i_ifaces ; i_index++ )
432 /* If interface has been found, return vlan */
433 if( !strcmp( p_method->p_iface[i_index].psz_name, psz_iface ) )
435 /* If interface is dependant, use master, else return own vlan */
436 return( (p_method->p_iface[i_index].i_master >= 0) ?
437 p_method->p_iface[p_method->p_iface[i_index].i_master].i_vlan :
438 p_method->p_iface[i_index].i_vlan );
442 /* If not found, return an error */
446 /*******************************************************************************
447 * input_VlanSynchronize: resynchronize with vlan server
448 *******************************************************************************
449 * Resynchronize with the vlan server. Vlans for all interfaces are requested
450 * and changed if required. This call may take a lot of time, and is intended
451 * for emergency situations.
452 *******************************************************************************/
453 int input_VlanSynchronize( void )
455 input_vlan_method_t * p_method; /* method global data */
456 input_vlan_iface_t * p_iface; /* interface (shortcut) */
457 int i_index; /* interface index */
458 int i_vlan; /* vlan for current interface */
461 p_method = p_main->p_input_vlan;
462 pthread_mutex_lock( &p_method->lock );
464 p_method = &p_program_data->input_vlan_method;
465 vlc_mutex_lock( &p_method->lock );
468 for( i_index = 0; i_index < p_method->i_ifaces; i_index++ )
470 p_iface = &p_method->p_iface[ i_index ];
472 /* Ignore dependant interfaces and interfaces for wich login failed */
473 if( (p_iface->i_master < 0) && !ServerLogin( &p_method->server ) )
475 /* Request interface informations */
476 i_vlan = p_iface->i_vlan;
477 if( !ServerRequestInfo( &p_method->server, p_iface ) )
479 /* If synchronization has been lost, then try to resynchronize -
480 * this part is ugly because of the vlan server bug requiring a
481 * logout between two requests */
482 if( p_iface->i_vlan != i_vlan )
484 intf_Msg("input: lost vlan synchronization for interface %s\n",
486 ServerLogout( &p_method->server );
487 if( !ServerLogin( &p_method->server ) )
489 if( !ServerRequestChange( &p_method->server, p_iface, i_vlan ) )
491 intf_Msg("input: retrieved vlan synchronization for interface %s\n",
495 /* Note that when this login fails, then the next logout will
496 * also fail... but I don't want to spend time finding a
497 * clean way to avoid this if the vlan server bug is fixed */
501 ServerLogout( &p_method->server );
506 vlc_mutex_unlock( &p_method->lock );
510 /* following functions are local */
512 /*******************************************************************************
513 * IfaceInfo: read info about an interface
514 *******************************************************************************
515 * This function reads informations about a network interface. It should return
516 * 0 and updated interface informations for vlan capable interfaces, and non 0
517 * if interface is not vlan-capable or informations request failed.
518 *******************************************************************************/
519 static int IfaceInfo( input_vlan_iface_t *p_iface )
524 /* Copy interface name */
525 strcpy(device.ifr_name, p_iface->psz_name);
527 /* Open a datagram socket */
528 i_socket = socket(AF_INET, SOCK_DGRAM, 0);
531 intf_ErrMsg("input error: unable to open socket on %s: %s\n",
532 p_iface->psz_name, strerror(errno));
536 /* Read IP address */
537 if(ioctl(i_socket, SIOCGIFDSTADDR, &device) < 0)
539 intf_ErrMsg("input error: can not read IP address for %s: %s\n",
540 p_iface->psz_name, strerror(errno));
543 memcpy( &p_iface->sa_in, &device.ifr_hwaddr, sizeof(struct sockaddr_in));
545 /* Read MAC address */
546 if(ioctl(i_socket, SIOCGIFHWADDR, &device) < 0)
548 intf_ErrMsg("input error: can not read MAC address for %s: %s\n",
549 p_iface->psz_name, strerror(errno));
553 /* Translate MAC address to ASCII standard */
554 sprintf(p_iface->psz_mac, "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
555 device.ifr_hwaddr.sa_data[0]&0xff,
556 device.ifr_hwaddr.sa_data[1]&0xff,
557 device.ifr_hwaddr.sa_data[2]&0xff,
558 device.ifr_hwaddr.sa_data[3]&0xff,
559 device.ifr_hwaddr.sa_data[4]&0xff,
560 device.ifr_hwaddr.sa_data[5]&0xff);
565 /*******************************************************************************
566 * IfaceDependance: check interface dependance
567 *******************************************************************************
568 * Check if an interface designed by it's index is dependant from another one.
569 * All the interfaces from 0 to i_index excluded are tested. If a 'master'
570 * interface is found, then the 'i_master' field is set to a positive value.
571 * Non 0 is returned if the interface is dependant.
572 *******************************************************************************/
573 static int IfaceDependance( input_vlan_method_t *p_method, int i_iface )
575 int i_index; /* interface index */
577 for( i_index = 0; i_index < i_iface; i_index++ )
579 /* Two interface are dependant if they are on the same switch and
581 if( ( p_method->p_iface[i_index].i_switch == p_method->p_iface[i_iface].i_switch )
582 && ( p_method->p_iface[i_index].i_port == p_method->p_iface[i_iface].i_port ) )
584 /* Interface is slave */
585 p_method->p_iface[i_iface].i_master = i_index;
590 /* Interface is master */
591 p_method->p_iface[i_iface].i_master = -1;
595 /*******************************************************************************
596 * ServerLogin: login to a vlan server
597 *******************************************************************************
598 * Initiate login sequence to a vlan server: open a socket, bind it and send
599 * login sequence. If the login fails for any reason, non 0 is returned.
600 *******************************************************************************/
601 static int ServerLogin( input_vlan_server_t *p_server )
603 struct sockaddr_in sa_client; /* client address */
604 char psz_msg[VLAN_SERVER_MSG_LENGTH + 1];/* server message */
605 int i_bytes; /* number of bytes read */
607 psz_msg[VLAN_SERVER_MSG_LENGTH] = '\0'; /* make sure the string ends */
609 /* Initialize local socket */
610 BuildInetAddr( &sa_client, NULL, 0 );
611 p_server->i_socket = socket(AF_INET, SOCK_STREAM, 0);
612 if( p_server->i_socket < 0 )
614 /* Error: return an error */
615 intf_ErrMsg("input error: can not open socket (%s)\n", strerror(errno));
619 /* Bind the server socket to client */
620 if( bind( p_server->i_socket, (struct sockaddr *) &sa_client, sizeof(sa_client)) < 0)
622 /* Error: close socket and return an error */
623 intf_ErrMsg("input error: can not bind socket (%s)\n", strerror(errno));
624 close( p_server->i_socket );
628 /* Try to connect to the VLANserver */
629 if( connect( p_server->i_socket, (struct sockaddr *) &p_server->sa_in,
630 sizeof(p_server->sa_in)) < 0)
632 /* Error: close socket and return an error */
633 intf_ErrMsg("input error: unable to connect to the VLAN server (%s)\n",
635 close( p_server->i_socket );
639 /* Send login message */
640 snprintf(psz_msg, VLAN_SERVER_MSG_LENGTH, "%d %s %s %s\n",
641 VLAN_LOGIN_REQUEST, VLAN_CLIENT_VERSION,
642 p_server->psz_login, p_server->psz_passwd );
643 if( send(p_server->i_socket, psz_msg, sizeof(char) * strlen( psz_msg ), 0) < 0)
645 intf_ErrMsg("input error: unable to login to the VLANserver: %s",
647 close( p_server->i_socket );
651 /* Listen to response */
652 i_bytes = recv(p_server->i_socket, psz_msg, VLAN_SERVER_MSG_LENGTH, 0);
655 intf_ErrMsg("input error: no response from VLANserver: %s\n",
657 ServerLogout( p_server );
661 /* Parse answer to login request */
662 psz_msg[ i_bytes ] = '\0'; /* terminate string */
663 if( atoi(psz_msg) == VLAN_LOGIN_REJECTED )
665 intf_ErrMsg("input error: login rejected by VLANserver: %s\n", psz_msg);
666 ServerLogout( p_server );
669 else if( atoi(psz_msg) != VLAN_LOGIN_ANSWER )
671 intf_ErrMsg("input error: unexpected answer from VLAN server: %s\n", psz_msg);
672 ServerLogout( p_server );
676 intf_DbgMsg("input debug: VLANserver login ok.\n");
680 /*******************************************************************************
681 * ServerLogout: logout from a vlan server
682 *******************************************************************************
683 * Logout from a vlan server. This function sends the logout message to the
684 * server and close the socket.
685 *******************************************************************************/
686 static void ServerLogout( input_vlan_server_t *p_server )
688 char psz_msg[VLAN_SERVER_MSG_LENGTH + 1]; /* server message */
690 psz_msg[VLAN_SERVER_MSG_LENGTH] = '\0'; /* make sure the string ends */
693 snprintf(psz_msg, VLAN_SERVER_MSG_LENGTH, "%d\n", VLAN_LOGOUT);
694 if( send(p_server->i_socket, psz_msg, sizeof(char) * strlen(psz_msg), 0) < 0)
696 intf_ErrMsg("input error: can't send logout message to VLANserver: %s\n",
701 if( close(p_server->i_socket) < 0)
703 intf_ErrMsg("input error: unable to close socket: %s\n", strerror(errno));
706 intf_DbgMsg("input debug: VLANserver logout ok\n");
709 /*******************************************************************************
710 * ServerRequestChange: request vlan change from a server
711 *******************************************************************************
712 * Request vlan change from a vlan server. The client must be logged in. If the
713 * change succeeded, the interface structure is updated. Note that only masters
714 * should be sent to this function.
715 *******************************************************************************/
716 static int ServerRequestChange( input_vlan_server_t *p_server,
717 input_vlan_iface_t *p_iface, int i_vlan )
719 char psz_msg[VLAN_SERVER_MSG_LENGTH + 1]; /* server message */
720 int i_bytes; /* number of bytes read */
722 psz_msg[VLAN_SERVER_MSG_LENGTH] = '\0'; /* make sure the string ends */
725 snprintf(psz_msg, VLAN_SERVER_MSG_LENGTH, "%d %s %s %d %d",
726 VLAN_CHANGE_REQUEST, p_iface->psz_mac,
727 inet_ntoa(p_iface->sa_in.sin_addr), i_vlan, p_iface->i_vlan);
728 if( send( p_server->i_socket, psz_msg, sizeof(char) * strlen(psz_msg), 0) < 0)
730 intf_ErrMsg("input error: unable to send request to VLANserver: %s\n",
735 /* Listen to response */
736 i_bytes = recv(p_server->i_socket, psz_msg, VLAN_SERVER_MSG_LENGTH, 0);
739 intf_ErrMsg("input error: no response from VLANserver: %s",
744 /* Parse answer to vlan request */
745 psz_msg[ i_bytes ] = '\0'; /* terminate string */
746 if( atoi( psz_msg ) == VLAN_CHANGE_REJECTED )
748 intf_ErrMsg("input error: change request rejected by VLANserver: %s\n", psz_msg );
751 else if( atoi( psz_msg ) != VLAN_CHANGE_ANSWER )
753 intf_ErrMsg("input error: unexpected answer from VLAN server: %s\n", psz_msg);
757 /* ?? send packet for the switch to learn mac again */
759 /* Update interface and return */
760 intf_DbgMsg("input debug: interface %s moved to vlan %d\n",
761 p_iface->psz_name, i_vlan );
762 p_iface->i_vlan = i_vlan;
766 /*******************************************************************************
767 * ServerRequestInfo: ask current vlan to server
768 *******************************************************************************
769 * Request current vlan from a vlan server. The client must be logged in. This
770 * function updates the p_iface structure or returns non 0. Note that only
771 * masters should be sent to this function.
772 *******************************************************************************/
773 static int ServerRequestInfo( input_vlan_server_t *p_server,
774 input_vlan_iface_t *p_iface )
776 char psz_msg[VLAN_SERVER_MSG_LENGTH + 1]; /* server message */
777 int i_bytes; /* number of bytes read */
778 int i_switch; /* switch number */
779 int i_port; /* port number */
780 int i_vlan; /* vlan number */
781 int i_sharers; /* number of mac addresses on this port */
783 psz_msg[VLAN_SERVER_MSG_LENGTH] = '\0'; /* make sure the string ends */
786 snprintf(psz_msg, VLAN_SERVER_MSG_LENGTH, "%d", VLAN_INFO_REQUEST);
787 if( send( p_server->i_socket, psz_msg, sizeof(char) * strlen(psz_msg), 0) < 0)
789 intf_ErrMsg("input error: unable to send request to VLANserver: %s\n",
794 /* Listen to response */
795 i_bytes = recv(p_server->i_socket, psz_msg, VLAN_SERVER_MSG_LENGTH, 0);
798 intf_ErrMsg("input error: no response from VLANserver: %s",
803 /* Parse answer to vlan request */
804 psz_msg[ i_bytes ] = '\0'; /* terminate string */
805 if( atoi( psz_msg ) == VLAN_INFO_REJECTED )
807 intf_ErrMsg("input error: info request rejected by VLANserver: %s\n", psz_msg );
810 else if( atoi( psz_msg ) != VLAN_INFO_ANSWER )
812 intf_ErrMsg("input error: unexpected answer from VLAN server: %s\n", psz_msg);
815 else if( sscanf(psz_msg, "%*d %d %d %d %d", &i_switch, &i_port, &i_vlan, &i_sharers) != 4 )
817 intf_ErrMsg("input error: invalid answer from VLAN server: %s\n", psz_msg);
821 /* Update interface and return */
822 intf_DbgMsg("input debug: interface %s is on switch %d, port %d, vlan %d, %d sharers\n",
823 p_iface->psz_name, i_switch, i_port, i_vlan, i_sharers);
824 p_iface->i_switch = i_switch;
825 p_iface->i_port = i_port;
826 p_iface->i_vlan = i_vlan;
827 p_iface->i_sharers = i_sharers;