libUPnP 1.14.19
Macros | Functions
gena_device.c File Reference
#include "config.h"
#include "gena_device.h"
#include <assert.h>
#include "gena.h"
#include "httpreadwrite.h"
#include "parsetools.h"
#include "ssdplib.h"
#include "statcodes.h"
#include "sysdep.h"
#include "unixutil.h"
#include "upnpapi.h"
#include "uuid.h"
#include "posix_overwrites.h"
Include dependency graph for gena_device.c:

Macros

#define STALE_JOBID   (INVALID_JOB_ID - 1)
 

Functions

int genaUnregisterDevice (UpnpDevice_Handle device_handle)
 Unregisters a device.
 
static int GeneratePropertySet (char **names, char **values, int count, DOMString *out)
 Generates XML property set for notifications.
 
static void free_notify_struct (notify_thread_struct *input)
 Frees memory used in notify_threads if the reference count is 0, otherwise decrements the refrence count.
 
static UPNP_INLINE int notify_send_and_recv (uri_type *destination_url, membuffer *mid_msg, char *propertySet, http_parser_t *response)
 Sends the notify message and returns a reply.
 
static int genaNotify (char *headers, char *propertySet, subscription *sub)
 Function to Notify a particular subscription of a particular event.
 
static void genaNotifyThread (void *input)
 Thread job to Notify a control point.
 
static char * AllocGenaHeaders (const DOMString propertySet)
 Allocates the GENA header.
 
void freeSubscriptionQueuedEvents (subscription *sub)
 
static int genaInitNotifyCommon (UpnpDevice_Handle device_handle, char *UDN, char *servId, DOMString propertySet, const Upnp_SID sid)
 
int genaInitNotify (UpnpDevice_Handle device_handle, char *UDN, char *servId, char **VarNames, char **VarValues, int var_count, const Upnp_SID sid)
 Sends the intial state table dump to newly subscribed control point.
 
int genaInitNotifyExt (UpnpDevice_Handle device_handle, char *UDN, char *servId, IXML_Document *PropSet, const Upnp_SID sid)
 Similar to the genaInitNofity. The only difference is that it takes the xml document for the state table and sends the intial state table dump to newly subscribed control point.
 
static void maybeDiscardEvents (LinkedList *listp)
 
static int genaNotifyAllCommon (UpnpDevice_Handle device_handle, char *UDN, char *servId, DOMString propertySet)
 
int genaNotifyAllExt (UpnpDevice_Handle device_handle, char *UDN, char *servId, IXML_Document *PropSet)
 Sends a notification to all the subscribed control points.
 
int genaNotifyAll (UpnpDevice_Handle device_handle, char *UDN, char *servId, char **VarNames, char **VarValues, int var_count)
 Sends a notification to all the subscribed control points.
 
static int respond_ok (SOCKINFO *info, int time_out, subscription *sub, http_message_t *request)
 Returns OK message in the case of a subscription request.
 
static int create_url_list (memptr *url_list, URL_list *out)
 Function to parse the Callback header value in subscription requests.
 
int gena_validate_delivery_urls (SOCKINFO *info, URL_list *url_list)
 Validate that the URLs passed by the user are on the same network segment than the device.
 
void gena_process_subscription_request (SOCKINFO *info, http_message_t *request)
 Handles a subscription request from a ctrl point. The socket is not closed on return.
 
void gena_process_subscription_renewal_request (SOCKINFO *info, http_message_t *request)
 Handles a subscription renewal request from a ctrl point. The connection is not destroyed on return.
 
void gena_process_unsubscribe_request (SOCKINFO *info, http_message_t *request)
 Handles a subscription cancellation request from a ctrl point. The connection is not destroyed on return.
 

Function Documentation

◆ AllocGenaHeaders()

static char * AllocGenaHeaders ( const DOMString  propertySet)
static

Allocates the GENA header.

Note
The header must be destroyed after with a call to free(), otherwise there will be a memory leak.
Returns
The constructed header.
Parameters
[in]propertySetThe property set string.

References UpnpPrintf().

◆ create_url_list()

static int create_url_list ( memptr url_list,
URL_list out 
)
static

Function to parse the Callback header value in subscription requests.

Takes in a buffer containing URLS delimited by '<' and '>'. The entire buffer is copied into dynamic memory and stored in the URL_list. Pointers to the individual urls within this buffer are allocated and stored in the URL_list. Only URLs with network addresses are considered (i.e. host:port or domain name).

Returns
The number of URLs parsed if successful, otherwise UPNP_E_OUTOF_MEMORY.
Parameters
[in]url_list.
[out]out.

References memptr::buf, memptr::length, parse_uri(), HOSTPORT::text, UPNP_E_OUTOF_MEMORY, and URL_LIST::URLs.

Referenced by gena_process_subscription_request().

◆ free_notify_struct()

static void free_notify_struct ( notify_thread_struct input)
static

Frees memory used in notify_threads if the reference count is 0, otherwise decrements the refrence count.

Parameters
[in]inputNotify structure.

References ixmlFreeDOMString().

Referenced by genaNotifyThread().

◆ gena_process_subscription_renewal_request()

void gena_process_subscription_renewal_request ( SOCKINFO info,
http_message_t request 
)

Handles a subscription renewal request from a ctrl point. The connection is not destroyed on return.

Parameters
[in]infoSocket info of the device.
[in]requestSubscription renewal request from the control point.

References memptr::buf, membuffer::buf, device_handle, SOCKINFO::foreign_sockaddr, GetDeviceHandleInfoForPath(), memptr::length, Handle_Info::MaxSubscriptions, Handle_Info::MaxSubscriptionTimeOut, PARSE_OK, respond_ok(), UPNP_E_SUCCESS, UpnpPrintf(), and http_message_t::uri.

Referenced by genaCallback().

◆ gena_process_subscription_request()

void gena_process_subscription_request ( SOCKINFO info,
http_message_t request 
)

◆ gena_process_unsubscribe_request()

void gena_process_unsubscribe_request ( SOCKINFO info,
http_message_t request 
)

Handles a subscription cancellation request from a ctrl point. The connection is not destroyed on return.

Parameters
[in]infoSocket info of the device.
[in]requestUNSUBSCRIBE request from the control point.

References memptr::buf, membuffer::buf, device_handle, SOCKINFO::foreign_sockaddr, GetDeviceHandleInfoForPath(), memptr::length, and http_message_t::uri.

Referenced by genaCallback().

◆ gena_validate_delivery_urls()

int gena_validate_delivery_urls ( SOCKINFO info,
URL_list url_list 
)

Validate that the URLs passed by the user are on the same network segment than the device.

Note: This is a fix for CallStanger a.k.a. CVE-2020-12695

Returns
0 if all URLs are on the same segment or -1 otherwise.
Parameters
[in]info.
[in]url_list.

References SOCKINFO::foreign_sockaddr, gIF_IPV4, gIF_IPV4_NETMASK, gIF_IPV6, gIF_IPV6_PREFIX_LENGTH, gIF_IPV6_ULA_GUA, gIF_IPV6_ULA_GUA_PREFIX_LENGTH, and UpnpPrintf().

Referenced by gena_process_subscription_request().

◆ genaInitNotify()

int genaInitNotify ( UpnpDevice_Handle  device_handle,
char *  UDN,
char *  servId,
char **  VarNames,
char **  VarValues,
int  var_count,
const Upnp_SID  sid 
)

Sends the intial state table dump to newly subscribed control point.

Returns
GENA_E_SUCCESS if successful, otherwise the appropriate error code.
Note
No other event will be sent to this control point before the intial state table dump.
Parameters
[in]device_handleDevice handle.
[in]UDNDevice udn.
[in]servIdService ID.
[in]VarNamesArray of variable names.
[in]VarValuesArray of variable values.
[in]var_countArray size.
[in]sidSubscription ID.

References device_handle, DOMString, GeneratePropertySet(), and UpnpPrintf().

Referenced by UpnpAcceptSubscription().

◆ genaInitNotifyExt()

int genaInitNotifyExt ( UpnpDevice_Handle  device_handle,
char *  UDN,
char *  servId,
IXML_Document PropSet,
const Upnp_SID  sid 
)

Similar to the genaInitNofity. The only difference is that it takes the xml document for the state table and sends the intial state table dump to newly subscribed control point.

Returns
GENA_E_SUCCESS if successful, otherwise the appropriate error code.
Note
No other event will be sent to this control point before the intial state table dump.
Parameters
[in]device_handleDevice handle.
[in]UDNDevice udn.
[in]servIdService ID.
[in]PropSetDocument of the state table.
[in]sidsubscription ID.

References device_handle, DOMString, ixmlPrintNode(), UPNP_E_INVALID_PARAM, and UpnpPrintf().

Referenced by UpnpAcceptSubscriptionExt().

◆ genaNotify()

static int genaNotify ( char *  headers,
char *  propertySet,
subscription sub 
)
static

Function to Notify a particular subscription of a particular event.

In general the service should NOT be blocked around this call (this may cause deadlock with a client).

NOTIFY http request is sent and the reply is processed.

Returns
GENA_SUCCESS if the event was delivered, otherwise returns the appropriate error code.
Parameters
[in]headersNull terminated, includes all headers (including \r\n) except SID and SEQ.
[in]propertySetThe evented XML.
[in]subsubscription to be Notified, assumes this is valid for life of function.

References http_MakeMessage(), notify_send_and_recv(), http_message_t::status_code, UPNP_E_OUTOF_MEMORY, and UPNP_E_SUCCESS.

Referenced by genaNotifyThread().

◆ genaNotifyAll()

int genaNotifyAll ( UpnpDevice_Handle  device_handle,
char *  UDN,
char *  servId,
char **  VarNames,
char **  VarValues,
int  var_count 
)

Sends a notification to all the subscribed control points.

Returns
int
Note
This function is similar to the genaNotifyAllExt. The only difference is it takes event variable array instead of xml document.
Parameters
[in]device_handleDevice handle.
[in]UDNDevice udn.
[in]servIdService ID.
[in]VarNamesArray of varible names.
[in]VarValuesArray of variable values.
[in]var_countNumber of variables.

References device_handle, DOMString, GeneratePropertySet(), and UpnpPrintf().

Referenced by UpnpNotify().

◆ genaNotifyAllExt()

int genaNotifyAllExt ( UpnpDevice_Handle  device_handle,
char *  UDN,
char *  servId,
IXML_Document PropSet 
)

Sends a notification to all the subscribed control points.

Returns
int
Note
This function is similar to the genaNotifyAll. the only difference is it takes the document instead of event variable array.
Parameters
[in]device_handleDevice handle.
[in]UDNDevice udn.
[in]servIdService ID.
[in]PropSetXML document Event varible property set.

References device_handle, DOMString, ixmlPrintNode(), UPNP_E_INVALID_PARAM, and UpnpPrintf().

Referenced by UpnpNotifyExt().

◆ genaNotifyThread()

static void genaNotifyThread ( void *  input)
static

Thread job to Notify a control point.

It validates the subscription and copies the subscription. Also make sure that events are sent in order.

Note
calls the genaNotify to do the actual work.
Parameters
[in]inputnotify thread structure containing all the headers and property set info.

References free_notify_struct(), genaNotify(), GetHandleInfo(), gSendThreadPool, Handle_Info::ServiceTable, and ThreadPoolAdd().

◆ genaUnregisterDevice()

int genaUnregisterDevice ( UpnpDevice_Handle  device_handle)

Unregisters a device.

Cleans the service table of the device.

Returns
UPNP_E_SUCCESS on success, GENA_E_BAD_HANDLE on failure.
Parameters
[in]device_handleDevice handle.

References device_handle, GetHandleInfo(), Handle_Info::ServiceTable, UPNP_E_SUCCESS, and UpnpPrintf().

Referenced by UpnpUnRegisterRootDeviceLowPower().

◆ GeneratePropertySet()

static int GeneratePropertySet ( char **  names,
char **  values,
int  count,
DOMString out 
)
static

Generates XML property set for notifications.

Returns
UPNP_E_SUCCESS if successful else returns GENA_E_BAD_HANDLE.
Note
The XML_VERSION comment is NOT sent due to interoperability issues with other UPnP vendors.
Parameters
[in]namesArray of variable names (go in the event notify).
[in]valuesArray of variable values (go in the event notify).
[in]countnumber of variables.
[out]outPropertySet node in the string format.

References ixmlCloneDOMString(), and UPNP_E_OUTOF_MEMORY.

Referenced by genaInitNotify(), and genaNotifyAll().

◆ notify_send_and_recv()

static UPNP_INLINE int notify_send_and_recv ( uri_type destination_url,
membuffer mid_msg,
char *  propertySet,
http_parser_t response 
)
static

Sends the notify message and returns a reply.

Returns
on success returns UPNP_E_SUCCESS, otherwise returns a UPNP error.
Note
called by genaNotify
Parameters
[in]destination_urlsubscription callback URL (URL of the control point).
[in]mid_msgCommon HTTP headers.
[in]propertySetThe evented XML.
[out]responseThe response from the control point.

References membuffer::buf, http_Connect(), http_MakeMessage(), http_RecvMessage(), http_SendMessage(), membuffer::length, sock_destroy(), sock_init(), HOSTPORT::text, UPNP_E_OUTOF_MEMORY, UPNP_E_SOCKET_CONNECT, UPNP_E_SUCCESS, and UpnpPrintf().

Referenced by genaNotify().

◆ respond_ok()

static int respond_ok ( SOCKINFO info,
int  time_out,
subscription sub,
http_message_t request 
)
static

Returns OK message in the case of a subscription request.

Returns
UPNP_E_SUCCESS if successful, otherwise the appropriate error code.
Parameters
[in]infoSocket connection of request.
[in]time_outAccepted duration.
[in]subAccepted subscription.
[in]requestHttp request.

References membuffer::buf, http_MakeMessage(), http_SendMessage(), membuffer::length, membuffer::size_inc, and UPNP_E_OUTOF_MEMORY.

Referenced by gena_process_subscription_renewal_request(), and gena_process_subscription_request().