1/* 2 * Copyright 2008-2013, Axel D��rfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6/*! Provides the networking stack notification service. */ 7 8#include <net_notifications.h> 9 10#include <kernel.h> 11#include <generic_syscall.h> 12#include <Notifications.h> 13#include <util/KMessage.h> 14 15//#define TRACE_NOTIFICATIONS 16#ifdef TRACE_NOTIFICATIONS 17# define TRACE(x...) dprintf("\33[32mnet_notifications:\33[0m " x) 18#else 19# define TRACE(x...) ; 20#endif 21 22 23class NetNotificationService : public DefaultUserNotificationService { 24public: 25 NetNotificationService(); 26 virtual ~NetNotificationService(); 27 28 void Notify(const KMessage& event); 29 30protected: 31 virtual void LastReferenceReleased(); 32 virtual void FirstAdded(); 33 virtual void LastRemoved(); 34}; 35 36 37static NetNotificationService sNotificationService; 38 39 40// #pragma mark - NetNotificationService 41 42 43NetNotificationService::NetNotificationService() 44 : 45 DefaultUserNotificationService("network") 46{ 47} 48 49 50NetNotificationService::~NetNotificationService() 51{ 52} 53 54 55void 56NetNotificationService::Notify(const KMessage& event) 57{ 58 uint32 opcode = event.GetInt32("opcode", 0); 59 if (opcode == 0) 60 return; 61 62 TRACE("notify for %lx\n", opcode); 63 64 DefaultUserNotificationService::Notify(event, opcode); 65} 66 67 68void 69NetNotificationService::LastReferenceReleased() 70{ 71 // don't delete us here 72} 73 74 75void 76NetNotificationService::FirstAdded() 77{ 78 // The reference counting doesn't work for us, as we'll have to 79 // ensure our module stays loaded. 80 module_info* dummy; 81 get_module(NET_NOTIFICATIONS_MODULE_NAME, &dummy); 82} 83 84 85void 86NetNotificationService::LastRemoved() 87{ 88 // Give up the reference _AddListener() 89 put_module(NET_NOTIFICATIONS_MODULE_NAME); 90} 91 92 93// #pragma mark - User generic syscall 94 95 96static status_t 97net_notifications_control(const char *subsystem, uint32 function, void *buffer, 98 size_t bufferSize) 99{ 100 struct net_notifications_control control; 101 if (bufferSize != sizeof(struct net_notifications_control) 102 || function != NET_NOTIFICATIONS_CONTROL_WATCHING) 103 return B_BAD_VALUE; 104 if (!IS_USER_ADDRESS(buffer) || user_memcpy(&control, buffer, 105 sizeof(struct net_notifications_control)) < B_OK) 106 return B_BAD_ADDRESS; 107 108 if (control.flags != 0) { 109 return sNotificationService.UpdateUserListener(control.flags, 110 control.port, control.token); 111 } 112 113 return sNotificationService.RemoveUserListeners(control.port, 114 control.token); 115} 116 117 118// #pragma mark - exported module API 119 120 121static status_t 122send_notification(const KMessage* event) 123{ 124 sNotificationService.Notify(*event); 125 return B_OK; 126} 127 128 129static status_t 130notifications_std_ops(int32 op, ...) 131{ 132 switch (op) { 133 case B_MODULE_INIT: 134 { 135 TRACE("init\n"); 136 137 new(&sNotificationService) NetNotificationService(); 138 status_t result = sNotificationService.Register(); 139 if (result != B_OK) 140 return result; 141 142 register_generic_syscall(NET_NOTIFICATIONS_SYSCALLS, 143 net_notifications_control, 1, 0); 144 return B_OK; 145 } 146 case B_MODULE_UNINIT: 147 TRACE("uninit\n"); 148 149 unregister_generic_syscall(NET_NOTIFICATIONS_SYSCALLS, 1); 150 151 // TODO: due to the way the locking in the notification 152 // manager works, there's a potential race condition here 153 // where someone attempts to add a listener right as 154 // we're uninitializing. Needs to be looked at/resolved. 155 sNotificationService.Unregister(); 156 157 // we need to release the reference that was acquired 158 // on our behalf by the NotificationManager. 159 sNotificationService.ReleaseReference(); 160 sNotificationService.~NetNotificationService(); 161 return B_OK; 162 163 default: 164 return B_ERROR; 165 } 166} 167 168 169net_notifications_module_info sNotificationsModule = { 170 { 171 NET_NOTIFICATIONS_MODULE_NAME, 172 0, 173 notifications_std_ops 174 }, 175 176 send_notification 177}; 178 179module_info* modules[] = { 180 (module_info*)&sNotificationsModule, 181 NULL 182}; 183