2008-08-29 01:05:01 +04:00
/*
* libudev - interface to udev device information
*
* Copyright ( C ) 2008 Kay Sievers < kay . sievers @ vrfy . org >
*
2009-03-26 21:29:36 +03:00
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation ; either
* version 2.1 of the License , or ( at your option ) any later version .
2008-08-29 01:05:01 +04:00
*/
# include <stdio.h>
# include <stdlib.h>
# include <stddef.h>
# include <unistd.h>
# include <errno.h>
# include <string.h>
# include <dirent.h>
# include <sys/stat.h>
# include <sys/socket.h>
# include <sys/un.h>
2008-09-09 19:38:10 +04:00
# include <linux/netlink.h>
2008-08-29 01:05:01 +04:00
# include "libudev.h"
# include "libudev-private.h"
struct udev_monitor {
struct udev * udev ;
int refcount ;
2008-09-08 19:59:00 +04:00
int sock ;
2008-09-09 19:38:10 +04:00
struct sockaddr_nl snl ;
2009-03-29 06:24:39 +04:00
struct sockaddr_nl snl_peer ;
2008-09-09 19:38:10 +04:00
struct sockaddr_un sun ;
2008-09-08 19:59:00 +04:00
socklen_t addrlen ;
2008-08-29 01:05:01 +04:00
} ;
2009-03-29 22:08:52 +04:00
enum udev_monitor_netlink_group {
UDEV_MONITOR_KERNEL = 1 ,
UDEV_MONITOR_UDEV = 2 ,
} ;
2008-08-30 18:16:37 +04:00
/**
* udev_monitor_new_from_socket :
* @ udev : udev library context
* @ socket_path : unix socket path
*
2009-04-16 03:49:16 +04:00
* Create new udev monitor and connect to a specified socket . The
* path to a socket either points to an existing socket file , or if
* the socket path starts with a ' @ ' character , an abstract namespace
2008-08-30 18:16:37 +04:00
* socket will be used .
*
2009-04-16 03:49:16 +04:00
* A socket file will not be created . If it does not already exist ,
* it will fall - back and connect to an abstract namespace socket with
* the given path . The permissions adjustment of a socket file , as
* well as the later cleanup , needs to be done by the caller .
*
2008-08-30 18:16:37 +04:00
* The initial refcount is 1 , and needs to be decremented to
2008-10-26 17:48:48 +03:00
* release the resources of the udev monitor .
2008-08-30 18:16:37 +04:00
*
* Returns : a new udev monitor , or # NULL , in case of an error
* */
2008-08-29 01:05:01 +04:00
struct udev_monitor * udev_monitor_new_from_socket ( struct udev * udev , const char * socket_path )
{
struct udev_monitor * udev_monitor ;
2008-10-10 01:38:30 +04:00
struct stat statbuf ;
2008-08-29 01:05:01 +04:00
if ( udev = = NULL )
return NULL ;
if ( socket_path = = NULL )
return NULL ;
2008-10-21 14:10:32 +04:00
udev_monitor = calloc ( 1 , sizeof ( struct udev_monitor ) ) ;
2008-08-29 01:05:01 +04:00
if ( udev_monitor = = NULL )
return NULL ;
udev_monitor - > refcount = 1 ;
udev_monitor - > udev = udev ;
2008-09-09 19:38:10 +04:00
udev_monitor - > sun . sun_family = AF_LOCAL ;
2008-10-15 16:20:27 +04:00
if ( socket_path [ 0 ] = = ' @ ' ) {
2008-10-10 01:38:30 +04:00
/* translate leading '@' to abstract namespace */
util_strlcpy ( udev_monitor - > sun . sun_path , socket_path , sizeof ( udev_monitor - > sun . sun_path ) ) ;
2008-09-09 19:38:10 +04:00
udev_monitor - > sun . sun_path [ 0 ] = ' \0 ' ;
2008-10-10 01:38:30 +04:00
udev_monitor - > addrlen = offsetof ( struct sockaddr_un , sun_path ) + strlen ( socket_path ) ;
2008-10-15 16:20:27 +04:00
} else if ( stat ( socket_path , & statbuf ) = = 0 & & S_ISSOCK ( statbuf . st_mode ) ) {
2008-10-10 01:38:30 +04:00
/* existing socket file */
util_strlcpy ( udev_monitor - > sun . sun_path , socket_path , sizeof ( udev_monitor - > sun . sun_path ) ) ;
udev_monitor - > addrlen = offsetof ( struct sockaddr_un , sun_path ) + strlen ( socket_path ) ;
} else {
/* no socket file, assume abstract namespace socket */
util_strlcpy ( & udev_monitor - > sun . sun_path [ 1 ] , socket_path , sizeof ( udev_monitor - > sun . sun_path ) - 1 ) ;
udev_monitor - > addrlen = offsetof ( struct sockaddr_un , sun_path ) + strlen ( socket_path ) + 1 ;
}
2008-09-08 19:59:00 +04:00
udev_monitor - > sock = socket ( AF_LOCAL , SOCK_DGRAM , 0 ) ;
if ( udev_monitor - > sock = = - 1 ) {
2008-09-29 19:01:32 +04:00
err ( udev , " error getting socket: %m \n " ) ;
2008-08-29 01:05:01 +04:00
free ( udev_monitor ) ;
return NULL ;
}
2009-04-06 13:18:41 +04:00
util_set_fd_cloexec ( udev_monitor - > sock ) ;
2008-11-01 22:16:24 +03:00
dbg ( udev , " monitor %p created with '%s' \n " , udev_monitor , socket_path ) ;
2008-09-08 19:59:00 +04:00
return udev_monitor ;
}
2008-08-29 01:05:01 +04:00
2009-04-16 03:49:16 +04:00
/**
* udev_monitor_new_from_netlink :
* @ udev : udev library context
* @ name : name of event source
*
* Create new udev monitor and connect to a specified event
* source . Valid sources identifiers are " udev " and " kernel " .
*
* Applications should usually not connect directly to the
* " kernel " events , because the devices might not be useable
* at that time , before udev has configured them , and created
* device nodes .
*
* Accessing devices at the same time as udev , might result
* in unpredictable behavior .
*
* The " udev " events are sent out after udev has finished its
* event processing , all rules have been processed , and needed
* device nodes are created .
*
* The initial refcount is 1 , and needs to be decremented to
* release the resources of the udev monitor .
*
* Returns : a new udev monitor , or # NULL , in case of an error
* */
2009-03-29 22:08:52 +04:00
struct udev_monitor * udev_monitor_new_from_netlink ( struct udev * udev , const char * name )
2008-09-09 19:38:10 +04:00
{
struct udev_monitor * udev_monitor ;
2009-03-29 22:08:52 +04:00
unsigned int group ;
2008-09-09 19:38:10 +04:00
if ( udev = = NULL )
return NULL ;
2009-03-29 22:08:52 +04:00
if ( name = = NULL )
return NULL ;
if ( strcmp ( name , " kernel " ) = = 0 )
group = UDEV_MONITOR_KERNEL ;
else if ( strcmp ( name , " udev " ) = = 0 )
group = UDEV_MONITOR_UDEV ;
else
return NULL ;
2008-10-21 14:10:32 +04:00
udev_monitor = calloc ( 1 , sizeof ( struct udev_monitor ) ) ;
2008-09-09 19:38:10 +04:00
if ( udev_monitor = = NULL )
return NULL ;
udev_monitor - > refcount = 1 ;
udev_monitor - > udev = udev ;
udev_monitor - > sock = socket ( PF_NETLINK , SOCK_DGRAM , NETLINK_KOBJECT_UEVENT ) ;
if ( udev_monitor - > sock = = - 1 ) {
2008-09-29 19:01:32 +04:00
err ( udev , " error getting socket: %m \n " ) ;
2008-09-09 19:38:10 +04:00
free ( udev_monitor ) ;
return NULL ;
}
2009-04-06 13:18:41 +04:00
util_set_fd_cloexec ( udev_monitor - > sock ) ;
2008-09-09 19:38:10 +04:00
udev_monitor - > snl . nl_family = AF_NETLINK ;
2009-03-29 06:24:39 +04:00
udev_monitor - > snl . nl_groups = group ;
udev_monitor - > snl_peer . nl_family = AF_NETLINK ;
udev_monitor - > snl_peer . nl_groups = UDEV_MONITOR_UDEV ;
2008-09-09 19:38:10 +04:00
2009-03-29 06:24:39 +04:00
dbg ( udev , " monitor %p created with NETLINK_KOBJECT_UEVENT (%u) \n " , udev_monitor , group ) ;
2008-09-09 19:38:10 +04:00
return udev_monitor ;
}
2008-09-08 19:59:00 +04:00
int udev_monitor_enable_receiving ( struct udev_monitor * udev_monitor )
{
int err ;
const int on = 1 ;
2009-04-08 18:46:54 +04:00
if ( udev_monitor - > sun . sun_family ! = 0 )
2009-03-29 06:24:39 +04:00
err = bind ( udev_monitor - > sock ,
( struct sockaddr * ) & udev_monitor - > sun , udev_monitor - > addrlen ) ;
2009-04-08 18:46:54 +04:00
else if ( udev_monitor - > snl . nl_family ! = 0 )
err = bind ( udev_monitor - > sock ,
( struct sockaddr * ) & udev_monitor - > snl , sizeof ( struct sockaddr_nl ) ) ;
else
return - EINVAL ;
if ( err < 0 ) {
err ( udev_monitor - > udev , " bind failed: %m \n " ) ;
return err ;
2008-08-29 01:05:01 +04:00
}
2009-04-08 18:46:54 +04:00
/* enable receiving of sender credentials */
setsockopt ( udev_monitor - > sock , SOL_SOCKET , SO_PASSCRED , & on , sizeof ( on ) ) ;
2008-09-08 19:59:00 +04:00
return 0 ;
2008-08-29 01:05:01 +04:00
}
2008-10-17 18:49:27 +04:00
int udev_monitor_set_receive_buffer_size ( struct udev_monitor * udev_monitor , int size )
{
if ( udev_monitor = = NULL )
return - 1 ;
return setsockopt ( udev_monitor - > sock , SOL_SOCKET , SO_RCVBUFFORCE , & size , sizeof ( size ) ) ;
}
2008-08-30 18:16:37 +04:00
/**
* udev_monitor_ref :
* @ udev_monitor : udev monitor
*
* Take a reference of a udev monitor .
*
* Returns : the passed udev monitor
* */
2008-08-29 01:05:01 +04:00
struct udev_monitor * udev_monitor_ref ( struct udev_monitor * udev_monitor )
{
if ( udev_monitor = = NULL )
return NULL ;
udev_monitor - > refcount + + ;
return udev_monitor ;
}
2008-08-30 18:16:37 +04:00
/**
* udev_monitor_unref :
* @ udev_monitor : udev monitor
*
2009-04-16 03:49:16 +04:00
* Drop a reference of a udev monitor . If the refcount reaches zero ,
2008-10-26 17:48:48 +03:00
* the bound socket will be closed , and the resources of the monitor
2008-08-30 18:16:37 +04:00
* will be released .
*
* */
2008-08-29 01:05:01 +04:00
void udev_monitor_unref ( struct udev_monitor * udev_monitor )
{
if ( udev_monitor = = NULL )
return ;
udev_monitor - > refcount - - ;
if ( udev_monitor - > refcount > 0 )
return ;
2008-09-08 19:59:00 +04:00
if ( udev_monitor - > sock > = 0 )
close ( udev_monitor - > sock ) ;
2008-11-01 22:16:24 +03:00
dbg ( udev_monitor - > udev , " monitor %p released \n " , udev_monitor ) ;
2008-08-29 01:05:01 +04:00
free ( udev_monitor ) ;
}
2008-08-30 18:16:37 +04:00
/**
* udev_monitor_get_udev :
* @ udev_monitor : udev monitor
*
2008-09-01 18:41:41 +04:00
* Retrieve the udev library context the monitor was created with .
2008-08-30 18:16:37 +04:00
*
* Returns : the udev library context
* */
2008-08-29 01:05:01 +04:00
struct udev * udev_monitor_get_udev ( struct udev_monitor * udev_monitor )
{
if ( udev_monitor = = NULL )
return NULL ;
return udev_monitor - > udev ;
}
2008-08-30 18:16:37 +04:00
/**
* udev_monitor_get_fd :
* @ udev_monitor : udev monitor
*
* Retrieve the socket file descriptor associated with the monitor .
*
* Returns : the socket file descriptor
* */
2008-08-29 01:05:01 +04:00
int udev_monitor_get_fd ( struct udev_monitor * udev_monitor )
{
if ( udev_monitor = = NULL )
return - 1 ;
2008-09-08 19:59:00 +04:00
return udev_monitor - > sock ;
2008-08-29 01:05:01 +04:00
}
2008-08-30 18:16:37 +04:00
/**
2008-09-08 19:59:00 +04:00
* udev_monitor_receive_device :
2008-08-30 18:16:37 +04:00
* @ udev_monitor : udev monitor
*
2008-09-08 19:59:00 +04:00
* Receive data from the udev monitor socket , allocate a new udev
2008-09-01 18:41:41 +04:00
* device , fill in the received data , and return the device .
2008-08-30 18:16:37 +04:00
*
* Only socket connections with uid = 0 are accepted . The caller
2008-10-26 17:48:48 +03:00
* needs to make sure that there is data to read from the socket .
* The call will block until the socket becomes readable .
2008-08-30 18:16:37 +04:00
*
* The initial refcount is 1 , and needs to be decremented to
2008-10-26 17:48:48 +03:00
* release the resources of the udev device .
2008-08-30 18:16:37 +04:00
*
* Returns : a new udev device , or # NULL , in case of an error
* */
2008-09-08 19:59:00 +04:00
struct udev_device * udev_monitor_receive_device ( struct udev_monitor * udev_monitor )
2008-08-29 01:05:01 +04:00
{
struct udev_device * udev_device ;
struct msghdr smsg ;
struct iovec iov ;
char cred_msg [ CMSG_SPACE ( sizeof ( struct ucred ) ) ] ;
2009-04-08 18:46:54 +04:00
struct cmsghdr * cmsg ;
2009-04-09 03:16:14 +04:00
struct sockaddr_nl snl ;
2009-04-08 18:46:54 +04:00
struct ucred * cred ;
2008-08-29 01:05:01 +04:00
char buf [ 4096 ] ;
size_t bufpos ;
2008-10-15 16:20:27 +04:00
int devpath_set = 0 ;
2008-10-16 13:37:22 +04:00
int subsystem_set = 0 ;
int action_set = 0 ;
2008-09-09 16:37:36 +04:00
int maj = 0 ;
int min = 0 ;
2008-08-29 01:05:01 +04:00
if ( udev_monitor = = NULL )
return NULL ;
memset ( buf , 0x00 , sizeof ( buf ) ) ;
iov . iov_base = & buf ;
iov . iov_len = sizeof ( buf ) ;
memset ( & smsg , 0x00 , sizeof ( struct msghdr ) ) ;
smsg . msg_iov = & iov ;
smsg . msg_iovlen = 1 ;
smsg . msg_control = cred_msg ;
smsg . msg_controllen = sizeof ( cred_msg ) ;
2009-04-09 03:16:14 +04:00
if ( udev_monitor - > snl . nl_family ! = 0 ) {
smsg . msg_name = & snl ;
smsg . msg_namelen = sizeof snl ;
}
2008-09-08 19:59:00 +04:00
if ( recvmsg ( udev_monitor - > sock , & smsg , 0 ) < 0 ) {
2008-08-29 01:05:01 +04:00
if ( errno ! = EINTR )
2009-04-09 03:16:14 +04:00
info ( udev_monitor - > udev , " unable to receive message \n " ) ;
2008-08-29 01:05:01 +04:00
return NULL ;
}
2009-04-09 03:16:14 +04:00
if ( udev_monitor - > snl . nl_family ! = 0 ) {
if ( snl . nl_groups = = 0 ) {
info ( udev_monitor - > udev , " unicast netlink message ignored \n " ) ;
return NULL ;
}
if ( ( snl . nl_groups = = UDEV_MONITOR_KERNEL ) & & ( snl . nl_pid > 0 ) ) {
info ( udev_monitor - > udev , " multicast kernel netlink message from pid %d ignored \n " , snl . nl_pid ) ;
return NULL ;
}
}
2009-04-08 18:46:54 +04:00
cmsg = CMSG_FIRSTHDR ( & smsg ) ;
if ( cmsg = = NULL | | cmsg - > cmsg_type ! = SCM_CREDENTIALS ) {
2009-04-09 03:16:14 +04:00
info ( udev_monitor - > udev , " no sender credentials received, message ignored \n " ) ;
2009-04-08 18:46:54 +04:00
return NULL ;
}
2008-09-09 19:38:10 +04:00
2009-04-08 18:46:54 +04:00
cred = ( struct ucred * ) CMSG_DATA ( cmsg ) ;
if ( cred - > uid ! = 0 ) {
2009-04-09 03:16:14 +04:00
info ( udev_monitor - > udev , " sender uid=%d, message ignored \n " , cred - > uid ) ;
2009-04-08 18:46:54 +04:00
return NULL ;
2008-08-29 01:05:01 +04:00
}
/* skip header */
bufpos = strlen ( buf ) + 1 ;
if ( bufpos < sizeof ( " a@/d " ) | | bufpos > = sizeof ( buf ) ) {
2009-04-09 03:16:14 +04:00
info ( udev_monitor - > udev , " invalid message length \n " ) ;
2008-08-29 01:05:01 +04:00
return NULL ;
}
/* check message header */
if ( strstr ( buf , " @/ " ) = = NULL ) {
2009-04-09 03:16:14 +04:00
info ( udev_monitor - > udev , " unrecognized message header \n " ) ;
2008-08-29 01:05:01 +04:00
return NULL ;
}
2008-09-30 18:16:29 +04:00
udev_device = device_new ( udev_monitor - > udev ) ;
2008-08-29 01:05:01 +04:00
if ( udev_device = = NULL ) {
return NULL ;
}
while ( bufpos < sizeof ( buf ) ) {
char * key ;
size_t keylen ;
key = & buf [ bufpos ] ;
keylen = strlen ( key ) ;
if ( keylen = = 0 )
break ;
bufpos + = keylen + 1 ;
if ( strncmp ( key , " DEVPATH= " , 8 ) = = 0 ) {
2008-09-16 04:12:47 +04:00
char path [ UTIL_PATH_SIZE ] ;
util_strlcpy ( path , udev_get_sys_path ( udev_monitor - > udev ) , sizeof ( path ) ) ;
util_strlcat ( path , & key [ 8 ] , sizeof ( path ) ) ;
2008-10-10 00:24:43 +04:00
udev_device_set_syspath ( udev_device , path ) ;
2008-10-15 16:20:27 +04:00
devpath_set = 1 ;
2008-08-29 01:05:01 +04:00
} else if ( strncmp ( key , " SUBSYSTEM= " , 10 ) = = 0 ) {
2008-10-10 00:24:43 +04:00
udev_device_set_subsystem ( udev_device , & key [ 10 ] ) ;
2008-10-16 13:37:22 +04:00
subsystem_set = 1 ;
2009-01-02 06:14:47 +03:00
} else if ( strncmp ( key , " DEVTYPE= " , 8 ) = = 0 ) {
udev_device_set_devtype ( udev_device , & key [ 8 ] ) ;
2008-08-29 01:05:01 +04:00
} else if ( strncmp ( key , " DEVNAME= " , 8 ) = = 0 ) {
2008-10-10 00:24:43 +04:00
udev_device_set_devnode ( udev_device , & key [ 8 ] ) ;
2008-08-29 01:05:01 +04:00
} else if ( strncmp ( key , " DEVLINKS= " , 9 ) = = 0 ) {
2008-10-15 18:55:04 +04:00
char devlinks [ UTIL_PATH_SIZE ] ;
char * slink ;
char * next ;
2008-08-29 01:05:01 +04:00
2008-10-15 18:55:04 +04:00
util_strlcpy ( devlinks , & key [ 9 ] , sizeof ( devlinks ) ) ;
slink = devlinks ;
next = strchr ( slink , ' ' ) ;
2008-08-29 01:05:01 +04:00
while ( next ! = NULL ) {
next [ 0 ] = ' \0 ' ;
2008-10-10 00:24:43 +04:00
udev_device_add_devlink ( udev_device , slink ) ;
2008-08-29 01:05:01 +04:00
slink = & next [ 1 ] ;
next = strchr ( slink , ' ' ) ;
}
if ( slink [ 0 ] ! = ' \0 ' )
2008-10-10 00:24:43 +04:00
udev_device_add_devlink ( udev_device , slink ) ;
2008-09-09 16:37:36 +04:00
} else if ( strncmp ( key , " DRIVER= " , 7 ) = = 0 ) {
2008-10-10 00:24:43 +04:00
udev_device_set_driver ( udev_device , & key [ 7 ] ) ;
2008-09-09 16:37:36 +04:00
} else if ( strncmp ( key , " ACTION= " , 7 ) = = 0 ) {
2008-10-10 00:24:43 +04:00
udev_device_set_action ( udev_device , & key [ 7 ] ) ;
2008-10-16 13:37:22 +04:00
action_set = 1 ;
2008-09-09 16:37:36 +04:00
} else if ( strncmp ( key , " MAJOR= " , 6 ) = = 0 ) {
maj = strtoull ( & key [ 6 ] , NULL , 10 ) ;
} else if ( strncmp ( key , " MINOR= " , 6 ) = = 0 ) {
min = strtoull ( & key [ 6 ] , NULL , 10 ) ;
} else if ( strncmp ( key , " DEVPATH_OLD= " , 12 ) = = 0 ) {
2008-10-10 00:24:43 +04:00
udev_device_set_devpath_old ( udev_device , & key [ 12 ] ) ;
2008-09-09 16:37:36 +04:00
} else if ( strncmp ( key , " PHYSDEVPATH= " , 12 ) = = 0 ) {
2008-10-10 00:24:43 +04:00
udev_device_set_physdevpath ( udev_device , & key [ 12 ] ) ;
2008-09-09 16:37:36 +04:00
} else if ( strncmp ( key , " SEQNUM= " , 7 ) = = 0 ) {
2008-10-10 00:24:43 +04:00
udev_device_set_seqnum ( udev_device , strtoull ( & key [ 7 ] , NULL , 10 ) ) ;
2008-09-09 16:37:36 +04:00
} else if ( strncmp ( key , " TIMEOUT= " , 8 ) = = 0 ) {
2008-10-10 00:24:43 +04:00
udev_device_set_timeout ( udev_device , strtoull ( & key [ 8 ] , NULL , 10 ) ) ;
2008-10-16 13:37:22 +04:00
} else if ( strncmp ( key , " PHYSDEV " , 7 ) = = 0 ) {
/* skip deprecated values */
2008-09-16 04:12:47 +04:00
continue ;
2008-10-16 13:37:22 +04:00
} else {
udev_device_add_property_from_string ( udev_device , key ) ;
}
2008-08-29 01:05:01 +04:00
}
2008-10-16 13:37:22 +04:00
if ( ! devpath_set | | ! subsystem_set | | ! action_set ) {
info ( udev_monitor - > udev , " missing values, skip \n " ) ;
2008-10-15 16:20:27 +04:00
udev_device_unref ( udev_device ) ;
return NULL ;
}
2008-10-16 20:56:19 +04:00
if ( maj > 0 )
udev_device_set_devnum ( udev_device , makedev ( maj , min ) ) ;
2008-10-10 00:24:43 +04:00
udev_device_set_info_loaded ( udev_device ) ;
2008-08-29 01:05:01 +04:00
return udev_device ;
}
2008-10-10 01:38:30 +04:00
int udev_monitor_send_device ( struct udev_monitor * udev_monitor , struct udev_device * udev_device )
{
2008-10-24 18:36:27 +04:00
const char * buf ;
ssize_t len ;
2008-10-10 01:38:30 +04:00
ssize_t count ;
2008-10-24 18:36:27 +04:00
len = udev_device_get_properties_monitor_buf ( udev_device , & buf ) ;
if ( len < 32 )
2008-10-24 17:09:43 +04:00
return - 1 ;
2009-04-08 18:46:54 +04:00
if ( udev_monitor - > sun . sun_family ! = 0 )
2009-03-29 06:24:39 +04:00
count = sendto ( udev_monitor - > sock ,
buf , len , 0 ,
( struct sockaddr * ) & udev_monitor - > sun ,
udev_monitor - > addrlen ) ;
2009-04-08 18:46:54 +04:00
else if ( udev_monitor - > snl . nl_family ! = 0 )
/* no destination besides the muticast group, we will always get ECONNREFUSED */
2009-03-29 06:24:39 +04:00
count = sendto ( udev_monitor - > sock ,
buf , len , 0 ,
( struct sockaddr * ) & udev_monitor - > snl_peer ,
sizeof ( struct sockaddr_nl ) ) ;
2009-04-08 18:46:54 +04:00
else
return - 1 ;
2009-04-09 03:16:14 +04:00
info ( udev_monitor - > udev , " passed %zi bytes to monitor %p \n " , count , udev_monitor ) ;
2008-10-10 01:38:30 +04:00
return count ;
}