Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
L
libplist
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
1
Issues
1
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
pwn
libplist
Commits
86f61988
Commit
86f61988
authored
Aug 31, 2008
by
Jonathan Beck
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
make all functions return an error code.
parent
dc89741f
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
197 additions
and
146 deletions
+197
-146
libiphone.h
include/libiphone/libiphone.h
+29
-27
AFC.c
src/AFC.c
+70
-60
iphone.c
src/iphone.c
+16
-9
lockdown.c
src/lockdown.c
+52
-32
usbmux.c
src/usbmux.c
+30
-18
No files found.
include/libiphone/libiphone.h
View file @
86f61988
...
...
@@ -46,6 +46,8 @@ extern "C" {
//afc specific error
#define IPHONE_E_NO_SUCH_FILE -10
typedef
short
iphone_error_t
;
enum
{
AFC_FILE_READ
=
0x00000002
,
// seems to be able to read and write files
AFC_FILE_WRITE
=
0x00000003
,
// writes and creates a file, blanks it out, etc.
...
...
@@ -73,44 +75,44 @@ struct iphone_afc_file_int;
typedef
struct
iphone_afc_file_int
*
iphone_afc_file_t
;
//device related functions
i
nt
iphone_get_device
(
iphone_device_t
*
device
);
void
iphone_free_device
(
iphone_device_t
device
);
i
phone_error_t
iphone_get_device
(
iphone_device_t
*
device
);
iphone_error_t
iphone_free_device
(
iphone_device_t
device
);
//lockdownd related functions
i
n
t
iphone_lckd_new_client
(
iphone_device_t
device
,
iphone_lckd_client_t
*
client
);
void
iphone_lckd_free_client
(
iphone_lckd_client_t
client
);
i
phone_error_
t
iphone_lckd_new_client
(
iphone_device_t
device
,
iphone_lckd_client_t
*
client
);
iphone_error_t
iphone_lckd_free_client
(
iphone_lckd_client_t
client
);
i
nt
iphone_lckd_start_service
(
iphone_lckd_client_t
client
,
const
char
*
service
);
i
nt
iphone_lckd_recv
(
iphone_lckd_client_t
client
,
char
**
dump_data
);
i
nt
iphone_lckd_send
(
iphone_lckd_client_t
client
,
char
*
raw_data
,
uint32_t
length
);
i
phone_error_t
iphone_lckd_start_service
(
iphone_lckd_client_t
client
,
const
char
*
service
,
int
*
port
);
i
phone_error_t
iphone_lckd_recv
(
iphone_lckd_client_t
client
,
char
**
dump_data
,
uint32_t
*
recv_bytes
);
i
phone_error_t
iphone_lckd_send
(
iphone_lckd_client_t
client
,
char
*
raw_data
,
uint32_t
length
,
uint32_t
*
recv_bytes
);
//usbmux related functions
i
n
t
iphone_mux_new_client
(
iphone_device_t
device
,
uint16_t
src_port
,
uint16_t
dst_port
,
iphone_umux_client_t
*
client
);
void
iphone_mux_free_client
(
iphone_umux_client_t
client
);
i
phone_error_
t
iphone_mux_new_client
(
iphone_device_t
device
,
uint16_t
src_port
,
uint16_t
dst_port
,
iphone_umux_client_t
*
client
);
iphone_error_t
iphone_mux_free_client
(
iphone_umux_client_t
client
);
i
nt
iphone_mux_send
(
iphone_umux_client_t
client
,
const
char
*
data
,
uint32_t
datalen
);
i
nt
iphone_mux_recv
(
iphone_umux_client_t
client
,
char
*
data
,
uint32_t
datalen
);
i
phone_error_t
iphone_mux_send
(
iphone_umux_client_t
client
,
const
char
*
data
,
uint32_t
datalen
,
uint32_t
*
sent_bytes
);
i
phone_error_t
iphone_mux_recv
(
iphone_umux_client_t
client
,
char
*
data
,
uint32_t
datalen
,
uint32_t
*
recv_bytes
);
//afc related functions
i
n
t
iphone_afc_new_client
(
iphone_device_t
device
,
int
src_port
,
int
dst_port
,
iphone_afc_client_t
*
client
);
void
iphone_afc_free_client
(
iphone_afc_client_t
client
);
char
**
iphone_afc_get_devinfo
(
iphone_afc_client_t
client
);
char
**
iphone_afc_get_dir_list
(
iphone_afc_client_t
client
,
const
char
*
dir
);
i
n
t
iphone_afc_get_file_attr
(
iphone_afc_client_t
client
,
const
char
*
filename
,
struct
stat
*
stbuf
);
i
n
t
iphone_afc_open_file
(
iphone_afc_client_t
client
,
const
char
*
filename
,
uint32_t
file_mode
,
iphone_afc_file_t
*
file
);
void
iphone_afc_close_file
(
iphone_afc_client_t
client
,
iphone_afc_file_t
file
);
i
nt
iphone_afc_read_file
(
iphone_afc_client_t
client
,
iphone_afc_file_t
file
,
char
*
data
,
int
length
);
i
nt
iphone_afc_write_file
(
iphone_afc_client_t
client
,
iphone_afc_file_t
file
,
const
char
*
data
,
int
length
);
i
n
t
iphone_afc_seek_file
(
iphone_afc_client_t
client
,
iphone_afc_file_t
file
,
int
seekpos
);
i
n
t
iphone_afc_truncate_file
(
iphone_afc_client_t
client
,
iphone_afc_file_t
file
,
uint32_t
newsize
);
i
n
t
iphone_afc_delete_file
(
iphone_afc_client_t
client
,
const
char
*
path
);
i
n
t
iphone_afc_rename_file
(
iphone_afc_client_t
client
,
const
char
*
from
,
const
char
*
to
);
i
n
t
iphone_afc_mkdir
(
iphone_afc_client_t
client
,
const
char
*
dir
);
i
phone_error_
t
iphone_afc_new_client
(
iphone_device_t
device
,
int
src_port
,
int
dst_port
,
iphone_afc_client_t
*
client
);
iphone_error_t
iphone_afc_free_client
(
iphone_afc_client_t
client
);
iphone_error_t
iphone_afc_get_devinfo
(
iphone_afc_client_t
client
,
char
***
infos
);
iphone_error_t
iphone_afc_get_dir_list
(
iphone_afc_client_t
client
,
const
char
*
dir
,
char
***
list
);
i
phone_error_
t
iphone_afc_get_file_attr
(
iphone_afc_client_t
client
,
const
char
*
filename
,
struct
stat
*
stbuf
);
i
phone_error_
t
iphone_afc_open_file
(
iphone_afc_client_t
client
,
const
char
*
filename
,
uint32_t
file_mode
,
iphone_afc_file_t
*
file
);
iphone_error_t
iphone_afc_close_file
(
iphone_afc_client_t
client
,
iphone_afc_file_t
file
);
i
phone_error_t
iphone_afc_read_file
(
iphone_afc_client_t
client
,
iphone_afc_file_t
file
,
char
*
data
,
int
length
,
uint32_t
*
bytes
);
i
phone_error_t
iphone_afc_write_file
(
iphone_afc_client_t
client
,
iphone_afc_file_t
file
,
const
char
*
data
,
int
length
,
uint32_t
*
bytes
);
i
phone_error_
t
iphone_afc_seek_file
(
iphone_afc_client_t
client
,
iphone_afc_file_t
file
,
int
seekpos
);
i
phone_error_
t
iphone_afc_truncate_file
(
iphone_afc_client_t
client
,
iphone_afc_file_t
file
,
uint32_t
newsize
);
i
phone_error_
t
iphone_afc_delete_file
(
iphone_afc_client_t
client
,
const
char
*
path
);
i
phone_error_
t
iphone_afc_rename_file
(
iphone_afc_client_t
client
,
const
char
*
from
,
const
char
*
to
);
i
phone_error_
t
iphone_afc_mkdir
(
iphone_afc_client_t
client
,
const
char
*
dir
);
#ifdef __cplusplus
...
...
src/AFC.c
View file @
86f61988
...
...
@@ -58,7 +58,7 @@ static void afc_unlock(iphone_afc_client_t client) { // just to be pretty
*
* @return A handle to the newly-connected client or NULL upon error.
*/
i
n
t
iphone_afc_new_client
(
iphone_device_t
device
,
int
src_port
,
int
dst_port
,
iphone_afc_client_t
*
client
)
{
i
phone_error_
t
iphone_afc_new_client
(
iphone_device_t
device
,
int
src_port
,
int
dst_port
,
iphone_afc_client_t
*
client
)
{
int
ret
=
IPHONE_E_SUCCESS
;
iphone_afc_client_t
client_loc
=
(
iphone_afc_client_t
)
malloc
(
sizeof
(
struct
iphone_afc_client_int
));
...
...
@@ -100,12 +100,14 @@ int iphone_afc_new_client ( iphone_device_t device, int src_port, int dst_port,
*
* @param client The client to disconnect.
*/
void
iphone_afc_free_client
(
iphone_afc_client_t
client
)
{
if
(
!
client
||
!
client
->
connection
||
!
client
->
afc_packet
)
return
;
iphone_error_t
iphone_afc_free_client
(
iphone_afc_client_t
client
)
{
if
(
!
client
||
!
client
->
connection
||
!
client
->
afc_packet
)
return
IPHONE_E_INVALID_ARG
;
iphone_mux_free_client
(
client
->
connection
);
free
(
client
->
afc_packet
);
free
(
client
);
return
IPHONE_E_SUCCESS
;
}
...
...
@@ -324,11 +326,12 @@ static char **make_strings_list(char *tokens, int true_length) {
* @return A char ** list of files in that directory, terminated by an empty
* string for now or NULL if there was an error.
*/
char
**
iphone_afc_get_dir_list
(
iphone_afc_client_t
client
,
const
char
*
dir
)
{
iphone_error_t
iphone_afc_get_dir_list
(
iphone_afc_client_t
client
,
const
char
*
dir
,
char
***
list
)
{
int
bytes
=
0
;
char
*
data
=
NULL
,
**
list
=
NULL
;
char
*
data
=
NULL
,
**
list_loc
=
NULL
;
iphone_error_t
ret
=
IPHONE_E_UNKNOWN_ERROR
;
if
(
!
client
||
!
dir
)
return
NULL
;
if
(
!
client
||
!
dir
||
!
list
)
return
IPHONE_E_INVALID_ARG
;
afc_lock
(
client
);
...
...
@@ -339,23 +342,25 @@ char **iphone_afc_get_dir_list ( iphone_afc_client_t client, const char *dir) {
bytes
=
dispatch_AFC_packet
(
client
,
dir
,
strlen
(
dir
));
if
(
bytes
<=
0
)
{
afc_unlock
(
client
);
return
NULL
;
return
IPHONE_E_NOT_ENOUGH_DATA
;
}
// Receive the data
bytes
=
receive_AFC_data
(
client
,
&
data
);
if
(
bytes
<
0
&&
!
data
)
{
afc_unlock
(
client
);
return
NULL
;
return
IPHONE_E_NOT_ENOUGH_DATA
;
}
// Parse the data
list
=
make_strings_list
(
data
,
bytes
);
list_loc
=
make_strings_list
(
data
,
bytes
);
if
(
list_loc
)
ret
=
IPHONE_E_SUCCESS
;
if
(
data
)
free
(
data
);
afc_unlock
(
client
);
*
list
=
list_loc
;
return
lis
t
;
return
re
t
;
}
/** Get device info for a client connection to phone. (free space on disk, etc.)
...
...
@@ -365,11 +370,11 @@ char **iphone_afc_get_dir_list ( iphone_afc_client_t client, const char *dir) {
* @return A char ** list of parameters as given by AFC or NULL if there was an
* error.
*/
char
**
iphone_afc_get_devinfo
(
iphone_afc_client_t
client
)
{
iphone_error_t
iphone_afc_get_devinfo
(
iphone_afc_client_t
client
,
char
***
infos
)
{
int
bytes
=
0
;
char
*
data
=
NULL
,
**
list
=
NULL
;
if
(
!
client
)
return
NULL
;
if
(
!
client
||
!
infos
)
return
IPHONE_E_INVALID_ARG
;
afc_lock
(
client
);
...
...
@@ -379,14 +384,14 @@ char **iphone_afc_get_devinfo ( iphone_afc_client_t client ) {
bytes
=
dispatch_AFC_packet
(
client
,
NULL
,
0
);
if
(
bytes
<
0
)
{
afc_unlock
(
client
);
return
NULL
;
return
IPHONE_E_NOT_ENOUGH_DATA
;
}
// Receive the data
bytes
=
receive_AFC_data
(
client
,
&
data
);
if
(
bytes
<
0
&&
!
data
)
{
afc_unlock
(
client
);
return
NULL
;
return
IPHONE_E_NOT_ENOUGH_DATA
;
}
// Parse the data
...
...
@@ -394,8 +399,8 @@ char **iphone_afc_get_devinfo ( iphone_afc_client_t client ) {
if
(
data
)
free
(
data
);
afc_unlock
(
client
);
return
list
;
*
infos
=
list
;
return
IPHONE_E_SUCCESS
;
}
/** Deletes a file.
...
...
@@ -406,7 +411,7 @@ char **iphone_afc_get_devinfo ( iphone_afc_client_t client ) {
* @return IPHONE_E_SUCCESS if everythong went well, IPHONE_E_INVALID_ARG
* if arguments are NULL or invalid, IPHONE_E_NOT_ENOUGH_DATA otherwise.
*/
i
n
t
iphone_afc_delete_file
(
iphone_afc_client_t
client
,
const
char
*
path
)
{
i
phone_error_
t
iphone_afc_delete_file
(
iphone_afc_client_t
client
,
const
char
*
path
)
{
char
*
response
=
NULL
;
int
bytes
;
...
...
@@ -445,7 +450,7 @@ int iphone_afc_delete_file ( iphone_afc_client_t client, const char *path) {
* @return IPHONE_E_SUCCESS if everythong went well, IPHONE_E_INVALID_ARG
* if arguments are NULL or invalid, IPHONE_E_NOT_ENOUGH_DATA otherwise.
*/
i
n
t
iphone_afc_rename_file
(
iphone_afc_client_t
client
,
const
char
*
from
,
const
char
*
to
)
{
i
phone_error_
t
iphone_afc_rename_file
(
iphone_afc_client_t
client
,
const
char
*
from
,
const
char
*
to
)
{
char
*
response
=
NULL
;
char
*
send
=
(
char
*
)
malloc
(
sizeof
(
char
)
*
(
strlen
(
from
)
+
strlen
(
to
)
+
1
+
sizeof
(
uint32
)));
int
bytes
=
0
;
...
...
@@ -488,7 +493,7 @@ int iphone_afc_rename_file ( iphone_afc_client_t client, const char *from, const
* @return IPHONE_E_SUCCESS if everythong went well, IPHONE_E_INVALID_ARG
* if arguments are NULL or invalid, IPHONE_E_NOT_ENOUGH_DATA otherwise.
*/
i
n
t
iphone_afc_mkdir
(
iphone_afc_client_t
client
,
const
char
*
dir
)
{
i
phone_error_
t
iphone_afc_mkdir
(
iphone_afc_client_t
client
,
const
char
*
dir
)
{
int
bytes
=
0
;
char
*
response
=
NULL
;
...
...
@@ -586,7 +591,7 @@ iphone_afc_file_t afc_get_file_info(iphone_afc_client_t client, const char *path
* @return A pointer to an AFCFile struct containing the information received,
* or NULL on failure.
*/
i
n
t
iphone_afc_get_file_attr
(
iphone_afc_client_t
client
,
const
char
*
filename
,
struct
stat
*
stbuf
)
{
i
phone_error_
t
iphone_afc_get_file_attr
(
iphone_afc_client_t
client
,
const
char
*
filename
,
struct
stat
*
stbuf
)
{
int
ret
=
IPHONE_E_SUCCESS
;
if
(
!
client
||!
client
->
connection
||
!
client
->
afc_packet
||
!
stbuf
)
return
IPHONE_E_INVALID_ARG
;
...
...
@@ -620,7 +625,7 @@ int iphone_afc_get_file_attr ( iphone_afc_client_t client, const char *filename,
* received by afc_get_file_info) as well as the handle to the file or
* NULL in the case of failure.
*/
i
n
t
iphone_afc_open_file
(
iphone_afc_client_t
client
,
const
char
*
filename
,
uint32_t
file_mode
,
iphone_afc_file_t
*
file
)
{
i
phone_error_
t
iphone_afc_open_file
(
iphone_afc_client_t
client
,
const
char
*
filename
,
uint32_t
file_mode
,
iphone_afc_file_t
*
file
)
{
iphone_afc_file_t
file_loc
=
NULL
;
uint32
ag
=
0
;
int
bytes
=
0
,
length
=
0
;
...
...
@@ -677,12 +682,12 @@ int iphone_afc_open_file ( iphone_afc_client_t client, const char *filename, uin
*
* @return The number of bytes read if successful. If there was an error -1.
*/
i
nt
iphone_afc_read_file
(
iphone_afc_client_t
client
,
iphone_afc_file_t
file
,
char
*
data
,
int
length
)
{
i
phone_error_t
iphone_afc_read_file
(
iphone_afc_client_t
client
,
iphone_afc_file_t
file
,
char
*
data
,
int
length
,
uint32_t
*
bytes
)
{
char
*
input
=
NULL
;
int
current_count
=
0
,
bytes
=
0
;
int
current_count
=
0
,
bytes
_loc
=
0
;
const
int
MAXIMUM_READ_SIZE
=
1
<<
16
;
if
(
!
client
||
!
client
->
afc_packet
||
!
client
->
connection
||
!
file
)
return
-
1
;
if
(
!
client
||
!
client
->
afc_packet
||
!
client
->
connection
||
!
file
)
return
IPHONE_E_INVALID_ARG
;
if
(
debug
)
fprintf
(
stderr
,
"afc_read_file called for length %i
\n
"
,
length
);
afc_lock
(
client
);
...
...
@@ -698,40 +703,41 @@ int iphone_afc_read_file ( iphone_afc_client_t client, iphone_afc_file_t file, c
packet
->
size
=
((
length
-
current_count
)
<
MAXIMUM_READ_SIZE
)
?
(
length
-
current_count
)
:
MAXIMUM_READ_SIZE
;
client
->
afc_packet
->
operation
=
AFC_READ
;
client
->
afc_packet
->
entire_length
=
client
->
afc_packet
->
this_length
=
0
;
bytes
=
dispatch_AFC_packet
(
client
,
(
char
*
)
packet
,
sizeof
(
AFCFilePacket
));
bytes
_loc
=
dispatch_AFC_packet
(
client
,
(
char
*
)
packet
,
sizeof
(
AFCFilePacket
));
free
(
packet
);
if
(
bytes
<=
0
)
{
if
(
bytes
_loc
<=
0
)
{
afc_unlock
(
client
);
return
-
1
;
return
IPHONE_E_NOT_ENOUGH_DATA
;
}
// Receive the data
bytes
=
receive_AFC_data
(
client
,
&
input
);
if
(
debug
)
fprintf
(
stderr
,
"afc_read_file: bytes returned: %i
\n
"
,
bytes
);
bytes
_loc
=
receive_AFC_data
(
client
,
&
input
);
if
(
debug
)
fprintf
(
stderr
,
"afc_read_file: bytes returned: %i
\n
"
,
bytes
_loc
);
if
(
bytes
<
0
)
{
if
(
input
)
free
(
input
);
afc_unlock
(
client
);
return
-
1
;
return
IPHONE_E_NOT_ENOUGH_DATA
;
}
else
if
(
bytes
==
0
)
{
if
(
input
)
free
(
input
);
afc_unlock
(
client
);
return
current_count
;
*
bytes
=
current_count
;
return
IPHONE_E_SUCCESS
;
//FIXME check that's actually a success
}
else
{
if
(
input
)
{
if
(
debug
)
fprintf
(
stderr
,
"afc_read_file: %d
\n
"
,
bytes
);
memcpy
(
data
+
current_count
,
input
,
(
bytes
>
length
)
?
length
:
bytes
);
if
(
debug
)
fprintf
(
stderr
,
"afc_read_file: %d
\n
"
,
bytes
_loc
);
memcpy
(
data
+
current_count
,
input
,
(
bytes
_loc
>
length
)
?
length
:
bytes_loc
);
free
(
input
);
input
=
NULL
;
current_count
+=
(
bytes
>
length
)
?
length
:
bytes
;
current_count
+=
(
bytes
_loc
>
length
)
?
length
:
bytes_loc
;
}
}
}
if
(
debug
)
fprintf
(
stderr
,
"afc_read_file: returning current_count as %i
\n
"
,
current_count
);
afc_unlock
(
client
);
return
current_count
;
*
bytes
=
current_count
;
return
IPHONE_E_SUCCESS
;
}
/** Writes a given number of bytes to a file.
...
...
@@ -744,13 +750,13 @@ int iphone_afc_read_file ( iphone_afc_client_t client, iphone_afc_file_t file, c
* @return The number of bytes written to the file, or a value less than 0 if
* none were written...
*/
i
nt
iphone_afc_write_file
(
iphone_afc_client_t
client
,
iphone_afc_file_t
file
,
const
char
*
data
,
int
length
)
{
i
phone_error_t
iphone_afc_write_file
(
iphone_afc_client_t
client
,
iphone_afc_file_t
file
,
const
char
*
data
,
int
length
,
uint32_t
*
bytes
)
{
char
*
acknowledgement
=
NULL
;
const
int
MAXIMUM_WRITE_SIZE
=
1
<<
16
;
uint32
zero
=
0
,
bytes
=
0
,
segments
=
(
length
/
MAXIMUM_WRITE_SIZE
),
current_count
=
0
,
i
=
0
;
uint32
zero
=
0
,
bytes
_loc
=
0
,
segments
=
(
length
/
MAXIMUM_WRITE_SIZE
),
current_count
=
0
,
i
=
0
;
char
*
out_buffer
=
NULL
;
if
(
!
client
||!
client
->
afc_packet
||
!
client
->
connection
||
!
file
)
return
-
1
;
if
(
!
client
||!
client
->
afc_packet
||
!
client
->
connection
||
!
file
||
!
bytes_loc
)
return
IPHONE_E_INVALID_ARG
;
afc_lock
(
client
);
...
...
@@ -766,19 +772,19 @@ int iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file,
memcpy
(
out_buffer
,
(
char
*
)
&
file
->
filehandle
,
sizeof
(
uint32
));
memcpy
(
out_buffer
+
4
,
(
char
*
)
&
zero
,
sizeof
(
uint32
));
memcpy
(
out_buffer
+
8
,
data
+
current_count
,
MAXIMUM_WRITE_SIZE
);
bytes
=
dispatch_AFC_packet
(
client
,
out_buffer
,
MAXIMUM_WRITE_SIZE
+
8
);
if
(
bytes
<
0
)
{
bytes
_loc
=
dispatch_AFC_packet
(
client
,
out_buffer
,
MAXIMUM_WRITE_SIZE
+
8
);
if
(
bytes
_loc
<
0
)
{
afc_unlock
(
client
);
return
bytes
;
return
IPHONE_E_NOT_ENOUGH_DATA
;
}
free
(
out_buffer
);
out_buffer
=
NULL
;
current_count
+=
bytes
;
bytes
=
receive_AFC_data
(
client
,
&
acknowledgement
);
if
(
bytes
<
0
)
{
current_count
+=
bytes
_loc
;
bytes
_loc
=
receive_AFC_data
(
client
,
&
acknowledgement
);
if
(
bytes
_loc
<
0
)
{
afc_unlock
(
client
);
return
current_count
;
return
IPHONE_E_NOT_ENOUGH_DATA
;
}
}
...
...
@@ -786,7 +792,8 @@ int iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file,
// this length is fine because it's always sizeof(AFCPacket) + 8, but to be sure we do it again
if
(
current_count
==
length
)
{
afc_unlock
(
client
);
return
current_count
;
*
bytes
=
current_count
;
return
IPHONE_E_SUCCESS
;
}
client
->
afc_packet
->
this_length
=
sizeof
(
AFCPacket
)
+
8
;
...
...
@@ -796,25 +803,26 @@ int iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file,
memcpy
(
out_buffer
,
(
char
*
)
&
file
->
filehandle
,
sizeof
(
uint32
));
memcpy
(
out_buffer
+
4
,
(
char
*
)
&
zero
,
sizeof
(
uint32
));
memcpy
(
out_buffer
+
8
,
data
+
current_count
,
(
length
-
current_count
));
bytes
=
dispatch_AFC_packet
(
client
,
out_buffer
,
(
length
-
current_count
)
+
8
);
bytes
_loc
=
dispatch_AFC_packet
(
client
,
out_buffer
,
(
length
-
current_count
)
+
8
);
free
(
out_buffer
);
out_buffer
=
NULL
;
current_count
+=
bytes
;
current_count
+=
bytes
_loc
;
if
(
bytes
<=
0
)
{
if
(
bytes
_loc
<=
0
)
{
afc_unlock
(
client
);
return
current_count
;
*
bytes
=
current_count
;
return
IPHONE_E_SUCCESS
;
}
zero
=
bytes
;
bytes
=
receive_AFC_data
(
client
,
&
acknowledgement
);
zero
=
bytes
_loc
;
bytes
_loc
=
receive_AFC_data
(
client
,
&
acknowledgement
);
afc_unlock
(
client
);
if
(
bytes
<
0
)
{
if
(
bytes
_loc
<
0
)
{
if
(
debug
)
fprintf
(
stderr
,
"afc_write_file: uh oh?
\n
"
);
}
return
current_count
;
return
IPHONE_E_UNKNOWN_ERROR
;
}
/** Closes a file on the phone.
...
...
@@ -823,7 +831,8 @@ int iphone_afc_write_file ( iphone_afc_client_t client, iphone_afc_file_t file,
* @param file A pointer to an AFCFile struct containing the file handle of the
* file to close.
*/
void
iphone_afc_close_file
(
iphone_afc_client_t
client
,
iphone_afc_file_t
file
)
{
iphone_error_t
iphone_afc_close_file
(
iphone_afc_client_t
client
,
iphone_afc_file_t
file
)
{
if
(
!
client
||
!
file
)
return
IPHONE_E_INVALID_ARG
;
char
*
buffer
=
malloc
(
sizeof
(
char
)
*
8
);
uint32
zero
=
0
;
int
bytes
=
0
;
...
...
@@ -846,7 +855,7 @@ void iphone_afc_close_file ( iphone_afc_client_t client, iphone_afc_file_t file)
if
(
bytes
<=
0
)
{
afc_unlock
(
client
);
return
;
return
IPHONE_E_UNKNOWN_ERROR
;
}
// Receive the response
...
...
@@ -854,6 +863,7 @@ void iphone_afc_close_file ( iphone_afc_client_t client, iphone_afc_file_t file)
if
(
buffer
)
free
(
buffer
);
free
(
file
);
afc_unlock
(
client
);
return
IPHONE_E_SUCCESS
;
}
/** Seeks to a given position of a pre-opened file on the phone.
...
...
@@ -865,7 +875,7 @@ void iphone_afc_close_file ( iphone_afc_client_t client, iphone_afc_file_t file)
*
* @return IPHONE_E_SUCCESS on success, IPHONE_E_NOT_ENOUGH_DATA on failure.
*/
i
n
t
iphone_afc_seek_file
(
iphone_afc_client_t
client
,
iphone_afc_file_t
file
,
int
seekpos
)
{
i
phone_error_
t
iphone_afc_seek_file
(
iphone_afc_client_t
client
,
iphone_afc_file_t
file
,
int
seekpos
)
{
char
*
buffer
=
(
char
*
)
malloc
(
sizeof
(
char
)
*
24
);
uint32
seekto
=
0
,
bytes
=
0
,
zero
=
0
;
...
...
@@ -916,7 +926,7 @@ int iphone_afc_seek_file ( iphone_afc_client_t client, iphone_afc_file_t file, i
* @note This function is more akin to ftruncate than truncate, and truncate
* calls would have to open the file before calling this, sadly.
*/
i
n
t
iphone_afc_truncate_file
(
iphone_afc_client_t
client
,
iphone_afc_file_t
file
,
uint32_t
newsize
)
{
i
phone_error_
t
iphone_afc_truncate_file
(
iphone_afc_client_t
client
,
iphone_afc_file_t
file
,
uint32_t
newsize
)
{
char
*
buffer
=
(
char
*
)
malloc
(
sizeof
(
char
)
*
16
);
uint32
bytes
=
0
,
zero
=
0
;
...
...
src/iphone.c
View file @
86f61988
...
...
@@ -34,7 +34,7 @@ extern int debug;
* @return A structure with data on the first iPhone it finds. (Or NULL, on
* error)
*/
i
nt
iphone_get_device
(
iphone_device_t
*
device
){
i
phone_error_t
iphone_get_device
(
iphone_device_t
*
device
){
//check we can actually write in device
if
(
!
device
||
(
device
&&
*
device
))
return
IPHONE_E_INVALID_ARG
;
...
...
@@ -134,14 +134,21 @@ int iphone_get_device ( iphone_device_t *device ){
*
* @param phone A pointer to an iPhone structure.
*/
void
iphone_free_device
(
iphone_device_t
device
)
{
if
(
device
->
buffer
)
free
(
device
->
buffer
);
iphone_error_t
iphone_free_device
(
iphone_device_t
device
)
{
if
(
!
device
)
return
IPHONE_E_INVALID_ARG
;
iphone_error_t
ret
=
IPHONE_E_UNKNOWN_ERROR
;
if
(
device
->
buffer
)
{
free
(
device
->
buffer
);
if
(
device
->
device
)
{
usb_release_interface
(
device
->
device
,
1
);
usb_reset
(
device
->
device
);
usb_close
(
device
->
device
);
ret
=
IPHONE_E_SUCCESS
;
}
free
(
device
);
}
return
ret
;
}
/** Sends data to the phone
...
...
src/lockdown.c
View file @
86f61988
...
...
@@ -94,15 +94,18 @@ iphone_lckd_client_t new_lockdownd_client(iphone_device_t phone) {
*
* @param control The lockdown client
*/
void
iphone_lckd_free_client
(
iphone_lckd_client_t
client
)
{
if
(
!
client
)
return
;
iphone_error_t
iphone_lckd_free_client
(
iphone_lckd_client_t
client
)
{
if
(
!
client
)
return
IPHONE_E_INVALID_ARG
;
iphone_error_t
ret
=
IPHONE_E_UNKNOWN_ERROR
;
if
(
client
->
connection
)
{
iphone_mux_free_client
(
client
->
connection
);
ret
=
iphone_mux_free_client
(
client
->
connection
);
}
if
(
client
->
ssl_session
)
gnutls_deinit
(
*
client
->
ssl_session
);
free
(
client
->
ssl_session
);
free
(
client
);
return
ret
;
}
/** Polls the iPhone for lockdownd data.
...
...
@@ -113,20 +116,28 @@ void iphone_lckd_free_client( iphone_lckd_client_t client ) {
*
* @return The number of bytes received
*/
int
iphone_lckd_recv
(
iphone_lckd_client_t
client
,
char
**
dump_data
)
{
if
(
!
client
)
return
0
;
iphone_error_t
iphone_lckd_recv
(
iphone_lckd_client_t
client
,
char
**
dump_data
,
uint32_t
*
recv_bytes
)
{
if
(
!
client
||
dump_data
||
!
recv_bytes
)
return
IPHONE_E_INVALID_ARG
;
iphone_error_t
ret
=
IPHONE_E_UNKNOWN_ERROR
;
char
*
receive
;
uint32
datalen
=
0
,
bytes
=
0
;
if
(
!
client
->
in_SSL
)
bytes
=
iphone_mux_recv
(
client
->
connection
,
(
char
*
)
&
datalen
,
sizeof
(
datalen
));
else
bytes
=
gnutls_record_recv
(
*
client
->
ssl_session
,
&
datalen
,
sizeof
(
datalen
));
if
(
!
client
->
in_SSL
)
ret
=
iphone_mux_recv
(
client
->
connection
,
(
char
*
)
&
datalen
,
sizeof
(
datalen
),
&
bytes
);
else
{
bytes
=
gnutls_record_recv
(
*
client
->
ssl_session
,
&
datalen
,
sizeof
(
datalen
));
if
(
bytes
>
0
)
ret
=
IPHONE_E_SUCCESS
;
}
datalen
=
ntohl
(
datalen
);
receive
=
(
char
*
)
malloc
(
sizeof
(
char
)
*
datalen
);
if
(
!
client
->
in_SSL
)
bytes
=
iphone_mux_recv
(
client
->
connection
,
receive
,
datalen
);
else
bytes
=
gnutls_record_recv
(
*
client
->
ssl_session
,
receive
,
datalen
);
if
(
!
client
->
in_SSL
)
ret
=
iphone_mux_recv
(
client
->
connection
,
receive
,
datalen
,
&
bytes
);
else
{
bytes
=
gnutls_record_recv
(
*
client
->
ssl_session
,
receive
,
datalen
);
if
(
bytes
>
0
)
ret
=
IPHONE_E_SUCCESS
;
}
*
dump_data
=
receive
;
return
bytes
;
*
recv_bytes
=
bytes
;
return
ret
;
}
/** Sends lockdownd data to the iPhone
...
...
@@ -140,10 +151,11 @@ int iphone_lckd_recv ( iphone_lckd_client_t client, char **dump_data ) {
*
* @return The number of bytes sent
*/
i
nt
iphone_lckd_send
(
iphone_lckd_client_t
client
,
char
*
raw_data
,
uint32_t
length
)
{
if
(
!
client
)
return
0
;
i
phone_error_t
iphone_lckd_send
(
iphone_lckd_client_t
client
,
char
*
raw_data
,
uint32_t
length
,
uint32_t
*
sent_bytes
)
{
if
(
!
client
||
!
raw_data
||
length
==
0
||
!
sent_bytes
)
return
IPHONE_E_INVALID_ARG
;
char
*
real_query
;
int
bytes
;
iphone_error_t
ret
=
IPHONE_E_UNKNOWN_ERROR
;
real_query
=
(
char
*
)
malloc
(
sizeof
(
char
)
*
(
length
+
4
));
length
=
htonl
(
length
);
...
...
@@ -157,11 +169,15 @@ int iphone_lckd_send ( iphone_lckd_client_t client, char *raw_data, uint32_t len
packet
=
NULL
;
}
if
(
!
client
->
in_SSL
)
bytes
=
iphone_mux_send
(
client
->
connection
,
real_query
,
ntohl
(
length
)
+
sizeof
(
length
));
else
gnutls_record_send
(
*
client
->
ssl_session
,
real_query
,
ntohl
(
length
)
+
sizeof
(
length
));
if
(
!
client
->
in_SSL
)
ret
=
iphone_mux_send
(
client
->
connection
,
real_query
,
ntohl
(
length
)
+
sizeof
(
length
),
&
bytes
);
else
{
gnutls_record_send
(
*
client
->
ssl_session
,
real_query
,
ntohl
(
length
)
+
sizeof
(
length
));
ret
=
IPHONE_E_SUCCESS
;
}
if
(
debug
)
printf
(
"lockdownd_send(): sent it!
\n
"
);
free
(
real_query
);
return
bytes
;
*
sent_bytes
=
bytes
;
return
ret
;
}
/** Initiates the handshake for the lockdown session. Part of the lockdownd handshake.
...
...
@@ -307,11 +323,11 @@ int lockdownd_get_device_public_key(iphone_lckd_client_t control, char **public_
*
* @return 1 on success and 0 on failure
*/
i
n
t
iphone_lckd_new_client
(
iphone_device_t
device
,
iphone_lckd_client_t
*
client
)
i
phone_error_
t
iphone_lckd_new_client
(
iphone_device_t
device
,
iphone_lckd_client_t
*
client
)
{
if
(
!
device
||
!
client
||
(
client
&&
*
client
)
)
return
IPHONE_E_INVALID_ARG
;
i
n
t
ret
=
IPHONE_E_SUCCESS
;
i
phone_error_
t
ret
=
IPHONE_E_SUCCESS
;
char
*
host_id
=
NULL
;
iphone_lckd_client_t
client_loc
=
new_lockdownd_client
(
device
);
...
...
@@ -815,14 +831,15 @@ ssize_t lockdownd_securead(gnutls_transport_ptr_t transport, char *buffer, size_
*
* @return The port number the service was started on or 0 on failure.
*/
i
nt
iphone_lckd_start_service
(
iphone_lckd_client_t
client
,
const
char
*
service
)
{
if
(
!
client
)
return
0
;
i
phone_error_t
iphone_lckd_start_service
(
iphone_lckd_client_t
client
,
const
char
*
service
,
int
*
port
)
{
if
(
!
client
||
!
service
||
!
port
)
return
IPHONE_E_INVALID_ARG
;
char
*
host_id
=
get_host_id
();
if
(
host_id
&&
!
client
->
in_SSL
&&
!
lockdownd_start_SSL_session
(
client
,
host_id
))
return
0
;
if
(
!
host_id
)
return
IPHONE_E_INVALID_CONF
;
if
(
!
client
->
in_SSL
&&
!
lockdownd_start_SSL_session
(
client
,
host_id
))
return
IPHONE_E_SSL_ERROR
;
char
*
XML_query
,
**
dictionary
;
uint32
length
,
i
=
0
,
port
=
0
;
uint32
length
,
i
=
0
,
port
_loc
=
0
;
uint8
result
=
0
;
free
(
host_id
);
...
...
@@ -832,9 +849,9 @@ int iphone_lckd_start_service ( iphone_lckd_client_t client, const char *service
xmlNode
*
dict
=
add_child_to_plist
(
plist
,
"dict"
,
"
\n
"
,
NULL
,
0
);
xmlNode
*
key
;
key
=
add_key_str_dict_element
(
plist
,
dict
,
"Request"
,
"StartService"
,
1
);
if
(
!
key
)
{
xmlFreeDoc
(
plist
);
return
0
;
}
if
(
!
key
)
{
xmlFreeDoc
(
plist
);
return
IPHONE_E_UNKNOWN_ERROR
;
}
key
=
add_key_str_dict_element
(
plist
,
dict
,
"Service"
,
service
,
1
);
if
(
!
key
)
{
xmlFreeDoc
(
plist
);
return
0
;
}
if
(
!
key
)
{
xmlFreeDoc
(
plist
);
return
IPHONE_E_UNKNOWN_ERROR
;
}
xmlDocDumpMemory
(
plist
,
(
xmlChar
**
)
&
XML_query
,
&
length
);
...
...
@@ -845,24 +862,24 @@ int iphone_lckd_start_service ( iphone_lckd_client_t client, const char *service
xmlFreeDoc
(
plist
);
if
(
length
<=
0
)
return
0
;
if
(
length
<=
0
)
return
IPHONE_E_NOT_ENOUGH_DATA
;
else
{
plist
=
xmlReadMemory
(
XML_query
,
length
,
NULL
,
NULL
,
0
);
if
(
!
plist
)
return
0
;
if
(
!
plist
)
return
IPHONE_E_UNKNOWN_ERROR
;
dict
=
xmlDocGetRootElement
(
plist
);
if
(
!
dict
)
return
0
;
if
(
!
dict
)
return
IPHONE_E_UNKNOWN_ERROR
;
for
(
dict
=
dict
->
children
;
dict
;
dict
=
dict
->
next
)
{
if
(
!
xmlStrcmp
(
dict
->
name
,
"dict"
))
break
;
}
if
(
!
dict
)
return
0
;
if
(
!
dict
)
return
IPHONE_E_UNKNOWN_ERROR
;
dictionary
=
read_dict_element_strings
(
dict
);
for
(
i
=
0
;
dictionary
[
i
];
i
+=
2
)
{
if
(
debug
)
printf
(
"lockdownd_start_service() dictionary %s: %s
\n
"
,
dictionary
[
i
],
dictionary
[
i
+
1
]);
if
(
!
xmlStrcmp
(
dictionary
[
i
],
"Port"
))
{
port
=
atoi
(
dictionary
[
i
+
1
]);
port
_loc
=
atoi
(
dictionary
[
i
+
1
]);
if
(
debug
)
printf
(
"lockdownd_start_service() atoi'd port: %i
\n
"
,
port
);
}
...
...
@@ -882,9 +899,12 @@ int iphone_lckd_start_service ( iphone_lckd_client_t client, const char *service
free
(
XML_query
);
xmlFreeDoc
(
plist
);
free_dictionary
(
dictionary
);
if
(
port
&&
result
)
return
port
;
else
return
0
;
if
(
port
&&
result
)
{
*
port
=
port_loc
;
return
IPHONE_E_SUCCESS
;
}
else
return
IPHONE_E_UNKNOWN_ERROR
;
}
return
0
;
return
IPHONE_E_UNKNOWN_ERROR
;
}
src/usbmux.c
View file @
86f61988
...
...
@@ -116,7 +116,7 @@ void add_connection(iphone_umux_client_t connection) {
* @param client A mux TCP header for the connection which is used for tracking and data transfer.
* @return IPHONE_E_SUCCESS on success, an error code otherwise.
*/
i
n
t
iphone_mux_new_client
(
iphone_device_t
device
,
uint16_t
src_port
,
uint16_t
dst_port
,
iphone_umux_client_t
*
client
){
i
phone_error_
t
iphone_mux_new_client
(
iphone_device_t
device
,
uint16_t
src_port
,
uint16_t
dst_port
,
iphone_umux_client_t
*
client
){
if
(
!
device
||
!
src_port
||
!
dst_port
)
return
IPHONE_E_INVALID_ARG
;
...
...
@@ -165,8 +165,10 @@ int iphone_mux_new_client ( iphone_device_t device, uint16_t src_port, uint16_t
* @note Once a connection is closed it may not be used again.
*
* @param connection The connection to close.
*
* @return IPHONE_E_SUCCESS on success.
*/
void
iphone_mux_free_client
(
iphone_umux_client_t
client
)
{
iphone_error_t
iphone_mux_free_client
(
iphone_umux_client_t
client
)
{
if
(
!
client
||
!
client
->
phone
)
return
;
client
->
header
->
tcp_flags
=
0x04
;
...
...
@@ -183,6 +185,8 @@ void iphone_mux_free_client ( iphone_umux_client_t client ) {
printf
(
"get_iPhone(): when reading, libusb gave me the error: %s
\n
"
,
usb_strerror
());
delete_connection
(
client
);
return
IPHONE_E_SUCCESS
;
}
...
...
@@ -192,15 +196,16 @@ void iphone_mux_free_client ( iphone_umux_client_t client ) {
* @param client The client we're sending data on.
* @param data A pointer to the data to send.
* @param datalen How much data we're sending.
* @param sent_bytes The number of bytes sent, minus the header (28)
*
* @return
The number of bytes sent, minus the header (28), or -1 on error
.
* @return
IPHONE_E_SUCCESS on success
.
*/
i
nt
iphone_mux_send
(
iphone_umux_client_t
client
,
const
char
*
data
,
uint32_t
datalen
)
{
if
(
!
client
->
phone
||
!
client
||
!
data
||
datalen
==
0
)
return
-
1
;
i
phone_error_t
iphone_mux_send
(
iphone_umux_client_t
client
,
const
char
*
data
,
uint32_t
datalen
,
uint32_t
*
sent_bytes
)
{
if
(
!
client
->
phone
||
!
client
||
!
data
||
datalen
==
0
||
!
sent_bytes
)
return
IPHONE_E_INVALID_ARG
;
// client->scnt and client->ocnt should already be in host notation...
// we don't need to change them juuuust yet.
int
bytes
=
0
;
*
sent_
bytes
=
0
;
if
(
debug
)
printf
(
"mux_send(): client wants to send %i bytes
\n
"
,
datalen
);
char
*
buffer
=
(
char
*
)
malloc
(
sizeof
(
usbmux_tcp_header
)
+
datalen
+
2
);
// allow 2 bytes of safety padding
// Set the length and pre-emptively htonl/htons it
...
...
@@ -218,12 +223,12 @@ int iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t da
if
(
debug
)
printf
(
"actually sending %zi bytes of data at %p
\n
"
,
sizeof
(
usbmux_tcp_header
)
+
datalen
,
buffer
);
bytes
=
send_to_phone
(
client
->
phone
,
buffer
,
sizeof
(
usbmux_tcp_header
)
+
datalen
);
if
(
debug
)
printf
(
"mux_send: sent %i bytes!
\n
"
,
bytes
);
*
sent_
bytes
=
send_to_phone
(
client
->
phone
,
buffer
,
sizeof
(
usbmux_tcp_header
)
+
datalen
);
if
(
debug
)
printf
(
"mux_send: sent %i bytes!
\n
"
,
*
sent_
bytes
);
// Now that we've sent it off, we can clean up after our sloppy selves.
if
(
debug
)
{
FILE
*
packet
=
fopen
(
"packet"
,
"a+"
);
fwrite
(
buffer
,
1
,
bytes
,
packet
);
fwrite
(
buffer
,
1
,
*
sent_
bytes
,
packet
);
fclose
(
packet
);
printf
(
"
\n
"
);
}
...
...
@@ -238,13 +243,14 @@ int iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t da
client
->
header
->
length16
=
ntohs
(
client
->
header
->
length16
);
// Now return the bytes.
if
(
bytes
<
sizeof
(
usbmux_tcp_header
)
+
datalen
)
{
return
-
1
;
// blah
if
(
*
sent_bytes
<
sizeof
(
usbmux_tcp_header
)
+
datalen
)
{
*
sent_bytes
=
0
;
return
IPHONE_E_NOT_ENOUGH_DATA
;
}
else
{
return
bytes
-
28
;
// actual length sent. :/
*
sent_bytes
=
*
sent_
bytes
-
28
;
// actual length sent. :/
}
return
bytes
;
// or something
return
IPHONE_E_UNKNOWN_ERROR
;
}
/** This is a higher-level USBMuxTCP-like function
...
...
@@ -255,7 +261,10 @@ int iphone_mux_send ( iphone_umux_client_t client, const char *data, uint32_t da
*
* @return How many bytes were read, or -1 if something bad happens.
*/
int
iphone_mux_recv
(
iphone_umux_client_t
client
,
char
*
data
,
uint32_t
datalen
)
{
iphone_error_t
iphone_mux_recv
(
iphone_umux_client_t
client
,
char
*
data
,
uint32_t
datalen
,
uint32_t
*
recv_bytes
)
{
if
(
!
client
||
!
data
||
datalen
==
0
||
!
recv_bytes
)
return
IPHONE_E_INVALID_ARG
;
/*
* Order of operation:
* 1.) Check if the client has a pre-received buffer.
...
...
@@ -268,6 +277,7 @@ int iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen
*/
if
(
debug
)
printf
(
"mux_recv: datalen == %i
\n
"
,
datalen
);
int
bytes
=
0
,
i
=
0
,
complex
=
0
,
offset
=
0
;
*
recv_bytes
=
0
;
char
*
buffer
=
NULL
;
usbmux_tcp_header
*
header
=
NULL
;
...
...
@@ -304,7 +314,7 @@ int iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen
if
(
bytes
<
28
)
{
free
(
buffer
);
if
(
debug
)
printf
(
"mux_recv: Did not even get the header.
\n
"
);
return
-
1
;
return
IPHONE_E_NOT_ENOUGH_DATA
;
}
header
=
(
usbmux_tcp_header
*
)
buffer
;
...
...
@@ -332,7 +342,7 @@ int iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen
// Free our buffer and continue.
free
(
buffer
);
buffer
=
NULL
;
return
iphone_mux_recv
(
client
,
data
,
datalen
);
// recurse back in to try again
return
iphone_mux_recv
(
client
,
data
,
datalen
,
recv_bytes
);
// recurse back in to try again
}
// The packet was absolutely meant for us if it hits this point.
...
...
@@ -348,13 +358,15 @@ int iphone_mux_recv ( iphone_umux_client_t client, char *data, uint32_t datalen
memcpy
(
client
->
recv_buffer
+
complex
,
buffer
+
28
+
datalen
,
(
bytes
-
28
)
-
datalen
);
free
(
buffer
);
client
->
header
->
ocnt
+=
bytes
-
28
;
return
datalen
;
*
recv_bytes
=
datalen
;
return
IPHONE_E_SUCCESS
;
}
else
{
// Fill the data with what we have, and just return.
memcpy
(
data
+
offset
,
buffer
+
28
,
bytes
-
28
);
// data+offset: see #2b, above
client
->
header
->
ocnt
+=
bytes
-
28
;
free
(
buffer
);
return
(
bytes
-
28
);
*
recv_bytes
=
bytes
-
28
;
return
IPHONE_E_SUCCESS
;
}
// If we get to this point, 'tis probably bad.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment