diff options
Diffstat (limited to 'fs/cifs/netmisc.c')
| -rw-r--r-- | fs/cifs/netmisc.c | 56 |
1 files changed, 52 insertions, 4 deletions
diff --git a/fs/cifs/netmisc.c b/fs/cifs/netmisc.c index 32d6baa0a54f..bd6d6895730d 100644 --- a/fs/cifs/netmisc.c +++ b/fs/cifs/netmisc.c | |||
| @@ -133,10 +133,12 @@ static const struct smb_to_posix_error mapping_table_ERRHRD[] = { | |||
| 133 | {0, 0} | 133 | {0, 0} |
| 134 | }; | 134 | }; |
| 135 | 135 | ||
| 136 | /* Convert string containing dotted ip address to binary form */ | 136 | /* |
| 137 | /* returns 0 if invalid address */ | 137 | * Convert a string containing text IPv4 or IPv6 address to binary form. |
| 138 | 138 | * | |
| 139 | int | 139 | * Returns 0 on failure. |
| 140 | */ | ||
| 141 | static int | ||
| 140 | cifs_inet_pton(const int address_family, const char *cp, void *dst) | 142 | cifs_inet_pton(const int address_family, const char *cp, void *dst) |
| 141 | { | 143 | { |
| 142 | int ret = 0; | 144 | int ret = 0; |
| @@ -153,6 +155,52 @@ cifs_inet_pton(const int address_family, const char *cp, void *dst) | |||
| 153 | return ret; | 155 | return ret; |
| 154 | } | 156 | } |
| 155 | 157 | ||
| 158 | /* | ||
| 159 | * Try to convert a string to an IPv4 address and then attempt to convert | ||
| 160 | * it to an IPv6 address if that fails. Set the family field if either | ||
| 161 | * succeeds. If it's an IPv6 address and it has a '%' sign in it, try to | ||
| 162 | * treat the part following it as a numeric sin6_scope_id. | ||
| 163 | * | ||
| 164 | * Returns 0 on failure. | ||
| 165 | */ | ||
| 166 | int | ||
| 167 | cifs_convert_address(char *src, void *dst) | ||
| 168 | { | ||
| 169 | int rc; | ||
| 170 | char *pct, *endp; | ||
| 171 | struct sockaddr_in *s4 = (struct sockaddr_in *) dst; | ||
| 172 | struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) dst; | ||
| 173 | |||
| 174 | /* IPv4 address */ | ||
| 175 | if (cifs_inet_pton(AF_INET, src, &s4->sin_addr.s_addr)) { | ||
| 176 | s4->sin_family = AF_INET; | ||
| 177 | return 1; | ||
| 178 | } | ||
| 179 | |||
| 180 | /* temporarily terminate string */ | ||
| 181 | pct = strchr(src, '%'); | ||
| 182 | if (pct) | ||
| 183 | *pct = '\0'; | ||
| 184 | |||
| 185 | rc = cifs_inet_pton(AF_INET6, src, &s6->sin6_addr.s6_addr); | ||
| 186 | |||
| 187 | /* repair temp termination (if any) and make pct point to scopeid */ | ||
| 188 | if (pct) | ||
| 189 | *pct++ = '%'; | ||
| 190 | |||
| 191 | if (!rc) | ||
| 192 | return rc; | ||
| 193 | |||
| 194 | s6->sin6_family = AF_INET6; | ||
| 195 | if (pct) { | ||
| 196 | s6->sin6_scope_id = (u32) simple_strtoul(pct, &endp, 0); | ||
| 197 | if (!*pct || *endp) | ||
| 198 | return 0; | ||
| 199 | } | ||
| 200 | |||
| 201 | return rc; | ||
| 202 | } | ||
| 203 | |||
| 156 | /***************************************************************************** | 204 | /***************************************************************************** |
| 157 | convert a NT status code to a dos class/code | 205 | convert a NT status code to a dos class/code |
| 158 | *****************************************************************************/ | 206 | *****************************************************************************/ |
